Search code examples
javascriptnode.jspromisestreamarray-map

How to simplify results of Promise.all/Streams/array_map Script Output


I have a short script that I run at command line that searches a variable amount of files for a number and returns the first line number for each file it is found within.

How can I alter the output of the file to return a single text line of the results and write it to a file? As well as return the count of how many of the variable number of files had the number, to a second file?

Script

const readline = require("readline");
const fs = require("fs");


const SearchFiles = (readStream, filePath, queries) => {
  let lineCount = 0;  
  let hold='';
  let matches = new Map();
  queries.forEach((query) => matches.set(query, []));

  return new Promise((resolve, reject) => { 
 
    readStream.on("line", (line) => {
      lineCount++;
      
      for (let query of matches.keys()) {
    
        if (searchForTerm(line, query))
        {
        matches.set(query, [...matches.get(query), lineCount]);  
         }}
});
  
    readStream.on("close", () =>
      resolve({
       filePath,
        matches,
      }) 
      
    );
 
  
  });
};
const searchForTerm = (line, query) => line.match(query);

const createLineInterfaces = (filePaths) =>
  filePaths.map((filePath) => {
    const readStream = readline.createInterface({
      input: fs.createReadStream(filePath),
    });
    return {
      filePath,
      readStream,
    };
  });
var lookup =56700;
var matchme =new RegExp("\\b" + lookup + "\\b");
const filesToSearch = ["/users/myname/desktop/mypath/threehundred_1191_37.txt", "/users/myname/desktop/mypath/threehundred_1191_37.txt", "/users/myname/desktop/mypath/threehundred_1191_36.txt", "/users/myname/desktop/mypath/threehundred_1191_35.txt", "/users/myname/desktop/mypath/threehundred_1191_38.txt", "/users/myname/desktop/mypath/threehundred_1191_39.txt", "/users/myname/desktop/mypath/threehundred_1191_40.txt", "/users/myname/desktop/mypath/threehundred_1191_41.txt"];
const queriesToSearch = [matchme];
let searchProms = createLineInterfaces(
  filesToSearch
).map(({ readStream, filePath }) =>
  SearchFiles(readStream, filePath, queriesToSearch)
);


Promise.all(searchProms).then((searchResults) =>
searchResults.forEach((result) => console.log(result))
)

Current Output

{
  filePath: '/users/myname/desktop/mypath/threehundred_1191_37.txt',
  matches: Map(1) { /\b56700\b/ => [ 52313 ] }
}

{
  filePath: '/users/myname/desktop/mypath/threehundred_1191_36.txt',
  matches: Map(1) { /\b56700\b/ => [ 52335 ] }
}
{
  filePath: '/users/myname/desktop/mypath/threehundred_1191_35.txt',
  matches: Map(1) { /\b56700\b/ => [] }
}
{
  filePath: '/users/myname/desktop/mypath/threehundred_1191_38.txt',
  matches: Map(1) { /\b56700\b/ => [ 52491 ] }
}
{
  filePath: '/users/myname/desktop/mypath/threehundred_1191_39.txt',
  matches: Map(1) { /\b56700\b/ => [ 52392 ] }
}
{
  filePath: '/users/myname/desktop/mypath/threehundred_1191_40.txt',
  matches: Map(1) { /\b56700\b/ => [ 52430 ] }
}
{
  filePath: '/users/myname/desktop/mypath/threehundred_1191_41.txt',
  matches: Map(1) { /\b56700\b/ => [ 52450 ] }
}
{
  filePath: '/users/myname/desktop/mypath/threehundred_1191_42.txt',
  matches: Map(1) { /\b56700\b/ => [ 52425 ] }
}

Wanted Output written to a First file

yes yes non yes yes yes yes yes

Wanted Output written to a Second file

 7

The yes/non string is in order that the files were given to search in the array. Yes means it is in file, non means it was not found.

Note I pretty much focus on PHP and python --- I just started nodejs 5 days ago and attempted this on my own with async/wait but it was no where as fast as this script... most likely because I have not mastered the .then, and promise.all with array_map.

I am at crunch time so the script above is being reused from this post below: How do I write the Regex for a Node app that acts like a simple JS linter with a condition as well


Solution

  • I was able to solve this isssue, with better organization of the coding as well as some significant optimization gain.

    THE NEW OPTIMIZED CODE

    const fs = require('fs');
    const readline = require('readline')
    
    
    const task_id = 1;
    
    let folder=1;
    let subfolder=1;
    let pastsearch=1;
    
    const myarray=[6567,50105,67637,293697];
    
    const mylen = myarray.length;
    
    const myfiles=['file_1.txt','file_2.txt'];
    
    
    fs.writeFile('/pathtomyfile/', '', function(){console.log('done')})
    
    
    fs.writeFile('/pathtomyfile/', '', function(){console.log('done')})
    
    
    
    
    const p1 = new Promise((resolve, reject) => {
      let lineCount = 0;
      
      let v=0;
    let yesnon = "non";
    
     let readStream = readline.createInterface({
                input: fs.createReadStream('/pathtofile/round_'+task_id+'/threehundred_'+folder+'/'+subfolder+'/'+myfiles[0],'utf8')
            });
    
        
      readStream.on("line", (line) => {
          lineCount++;
    
    if(line==pastsearch)
    {
    yesnon="yes";
    
    v++;
    }
          
        });
        
        readStream.on('end', () => {
      console.log('end');
      readStream.destroy();
    });
    
    
        readStream.on("close", () =>
          resolve({
           yesnon
          }) 
      
      )
      
      
      
    });
    
    const p2 = new Promise((resolve, reject) => {
    
     let readStream = readline.createInterface({
                input: fs.createReadStream('/pathtofile/round_'+task_id+'/threehundred_'+folder+'/'+subfolder+'/'+myfiles[1],'utf8')
            });
    
     let lineCount = 0;  let v=0;
    let yesnon = "non";
    
      readStream.on("line", (line) => {
          lineCount++;
    
    if(line==pastsearch)
    {
    yesnon="yes";
    
    v++;
    }
          
        });
      
      
       readStream.on('end', () => {
      console.log('end');
      readStream.destroy();
    });
    
    
        readStream.on("close", () =>
          resolve({
       yesnon
          }) )
      
      
    });
    
    
    
    
    for(let h=0; h<3; h++)
    {
    
    folder++
    subfolder++
    pastsearch=myarray[h];
    
    Promise.all([p1, p2]).then((results) => {
      
    const output = results.map( ({yesnon}) => yesnon).join(' ');
    
    fs.appendFileSync('/pathtofile/plain_round'+task_id+'.txt',output+"\n", 'utf8');
    
    const output2 = results.map( ({yesnon}) => yesnon);
    
    
    let count = 0;
    
    function countValues(array, countItem) {
      array.forEach(itm => {
        if (itm == countItem) count++;
      });
    
     return count;
    }
    const myresult34=countValues(output2, "yes");
    
    
    fs.appendFileSync('/pathtofile/round'+task_id+'.txt',myresult34+"\n", 'utf8');
    
    
    });
    }