Версия для печати
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум на Исходниках.RU > JavaScript, DOM/DHTML >  Compare text files


Автор: Cfon 25.09.18, 12:58
На Node.js асинхронный вариант будет выглядеть как то так:
<{CODE_COLLAPSE_OFF}><{CODE_WRAP_OFF}>
    const fs = require('fs');
     
    const asyncReadFile = fileName => {
      return new Promise((resolve, reject) => {
        fs.readFile(fileName, 'utf-8', (err, data) => {
          if (err) {
            return reject(new Error('Error reading file.'));
          }
          resolve(data);
        });
      });
    }
     
    const asyncWriteFile = (fileName, data) => {
      return new Promise((resolve, reject) => {
        fs.writeFile(fileName, data, err => {
          if (err) {
            return reject(new Error('Error writing file.'));
          }
          resolve('File saved.');
        });
      });
    }
     
    Promise.all([asyncReadFile('test1.txt'), asyncReadFile('test2.txt')])
      .then(data => {
        var data1 = data[0].trim().split('\n');
        var data2 = data[1].trim().split('\n');
        var results = [];
        var isFound;
     
        // Надо удалить циклы for
        for (var i = 0; i < data2.length; i++) {
          isFound = false;
          for (var j = 0; j < data1.length; j++) {
            if (data2[i].indexOf(data1[j]) === 0) {
              isFound = true;
              break;
            }
          }
          if (!isFound) {
            results.push(data2[i]);
          }
        }
     
        asyncWriteFile('test3.txt', results.join('\n'))
          .then(log => console.log(log))
          .catch(err => console.log(err));
      })
      .catch(err => {
        console.log(err);
      });

Как удалить циклы for? Ну т.е заюзать функциональное программирование?

Автор: Cfon 25.09.18, 17:04
Сам все порешал :D
<{CODE_COLLAPSE_OFF}><{CODE_WRAP_OFF}>
    Promise.all([asyncReadFile('test1.txt'), asyncReadFile('test2.txt')])
      .then(data => {
        var data1 = data[0].trim().split('\n');
        var data2 = data[1].trim().split('\n');
        var results = [];
        
        // юзаем функции Array вместо циклов for
        data2.forEach(str2 => {
          const isEqual = str1 => str2.localeCompare(str1) === 0;
          if (!data1.some(isEqual)) {
            results.push(str2);
          }
        });
     
        asyncWriteFile('test3.txt', results.join('\n'))
          .then(log => console.log(log))
          .catch(err => console.log(err));
      })
      .catch(err => {
        console.log(err);
      });

Попутно исправил один касяк, а именно заменил indexOf на localeCompare.

Автор: Cfon 26.09.18, 04:44
Продолжаю совершенствовать код :D
<{CODE_COLLAPSE_OFF}><{CODE_WRAP_OFF}>
    Promise.all([asyncReadFile('test1.txt'), asyncReadFile('test2.txt')])
      .then(data => {
        const data1 = data[0].trim().split('\n');
        const data2 = data[1].trim().split('\n');
     
        const results = data2.filter(str2 => {
          const isEqual = str1 => str2.localeCompare(str1) === 0;
          return !data1.some(isEqual);
        });
     
        asyncWriteFile('test3.txt', results.join('\n'))
          .then(log => console.log(log))
          .catch(err => console.log(err));
      })
      .catch(err => {
        console.log(err);
      });

заменил forEach на filter.

Автор: Cfon 26.09.18, 06:49
для тех кто любит Array.prototype.reduce :D
<{CODE_COLLAPSE_OFF}><{CODE_WRAP_OFF}>
    Promise.all([asyncReadFile('test1.txt'), asyncReadFile('test2.txt')])
      .then(data => {
        const data1 = data[0].trim().split('\n');
        const data2 = data[1].trim().split('\n');
     
        const results = data2.reduce((accum, str2) => {
          const isEqual = str1 => str2.localeCompare(str1) === 0;
          return data1.some(isEqual) ? accum : [...accum, str2];
        }, [] );
     
        asyncWriteFile('test3.txt', results.join('\n'))
          .then(log => console.log(log))
          .catch(err => console.log(err));
      })
      .catch(err => {
        console.log(err);
      });

Автор: Cfon 26.09.18, 11:33
Заключительный штрих, высший пилотаж! :D
Юзаем композицию
<{CODE_COLLAPSE_OFF}><{CODE_WRAP_OFF}>
    const compose = (...fns) =>
      fns.reduceRight((prevFn, nextFn) =>
        (...args) => nextFn(prevFn(...args)),
        value => value
      );
     
    const trimAndSplit = data => [
      data[0].trim().split('\n'),
      data[1].trim().split('\n')
    ];
     
    const getDiff = data => data[1].filter(str2 => {
      const isEqual = str1 => str2.localeCompare(str1) === 0;
      return !data[0].some(isEqual);
    });
     
    const save = fileName => data => {
      asyncWriteFile(fileName, data.join('\n'))
        .then(log => console.log(log))
        .catch(err => console.log(err));
    };
     
    Promise.all([asyncReadFile('test1.txt'), asyncReadFile('test2.txt')])
      .then(data => {
        compose(
          save('test3.txt'),
          getDiff,
          trimAndSplit
        )(data);
      })
      .catch(err => {
        console.log(err);
      });

Автор: Cfon 27.09.18, 08:31
Обнаружил касяк с выполнением асинхронногр вызова save. Заменил на асинхронный compose :D
<{CODE_COLLAPSE_OFF}><{CODE_WRAP_OFF}>
    // Async compose
    const compose = (...fns) => arg =>
      fns.reduceRight(
        (accum, fn) => accum.then(fn),
        Promise.resolve(arg)
      );

Высший пилотаж! :blush:

Касяк в том, что если добавить функцию в compose после save, то вызов этой функции будет выполнен перед save!
<{CODE_COLLAPSE_OFF}><{CODE_WRAP_OFF}>
    Promise.all([asyncReadFile('test1.txt'), asyncReadFile('test2.txt')])
      .then(data => {
        compose(
          val => console.log('to do something with `val`.'), // 4 - val is undefined
          save('test3.txt'), // 3 <-- async call
          getDiff,           // 2
          trimAndSplit       // 1
        )(data)
      })
      .catch(err => console.log(err));

Говоря по нормальному асинхронный вызов save не синхронизирован с остальными вызовами функций.

Powered by Invision Power Board (https://www.invisionboard.com)
© Invision Power Services (https://www.invisionpower.com)