На главную Наши проекты:
Журнал   ·   Discuz!ML   ·   Wiki   ·   DRKB   ·   Помощь проекту
ПРАВИЛА FAQ Помощь Участники Календарь Избранное RSS
msm.ru
Модераторы: ElcnU, ANDLL, fatalist
  
>  Compare text files
    На Node.js асинхронный вариант будет выглядеть как то так:
    ExpandedWrap disabled
      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? Ну т.е заюзать функциональное программирование?
      Сам все порешал :D
      ExpandedWrap disabled
        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 -
        Продолжаю совершенствовать код :D
        ExpandedWrap disabled
          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.
          для тех кто любит Array.prototype.reduce :D
          ExpandedWrap disabled
            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);
              });
            Заключительный штрих, высший пилотаж! :D
            Юзаем композицию
            ExpandedWrap disabled
              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 -
              Обнаружил касяк с выполнением асинхронногр вызова save. Заменил на асинхронный compose :D
              ExpandedWrap disabled
                // Async compose
                const compose = (...fns) => arg =>
                  fns.reduceRight(
                    (accum, fn) => accum.then(fn),
                    Promise.resolve(arg)
                  );

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

              Касяк в том, что если добавить функцию в compose после save, то вызов этой функции будет выполнен перед save!
              ExpandedWrap disabled
                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 не синхронизирован с остальными вызовами функций.
              Сообщение отредактировано: Cfon -
              0 пользователей читают эту тему (0 гостей и 0 скрытых пользователей)
              0 пользователей:


              Рейтинг@Mail.ru
              [ Script execution time: 0,0255 ]   [ 16 queries used ]   [ Generated: 28.03.24, 17:11 GMT ]