Search code examples
node.jsnode-csv-parse

Returning dictionary created from CSV parser


I'm trying extract dictionary data like {Name:Value, Name2:Value2,...} from csv file like below

<metadata>
<metadata>
<metadata>
<metadata>
ID,1,2,3,4,5,6,...
Name,ABC,BCD,CDE,DEF,EFG,FGH,...
Val,123,234,345,456,567,678,...

using the function below

async function getMap(file) {
  rv = {};
  fs.createReadStream(file)
    .pipe(csv.parse({from_line: 5, to_line:7, columns: true, bom: true}, (err, data) => {
      for(i=1;i<=200;i++) {
          rv[data[0][i]] = data[1][i];
      }
  }));
  return rv;
}

I thought this would return something like below:

{'ABC':123,'BCD':234,...}

But empty value was return. I'm sure it's something to do with scope (if that's the right word), but couldn't figure it out yet.

==============================
Initially I thought this is something to do wit scope, but more I looked into the result, it is more of asynchronous issue which I don't understand even more. How could this wait for readStream to process till the end of file, using await, promise, resolve, etc.


Solution

  • I've tested the code below, and it produces the desired map.

    If we get an error I'll call reject(err), so this should be propagated correctly. Should the parsing succeed, we'll call resolve with the required map.

    const csv = require('csv');
    const fs = require("fs");
    
    function getMap(file) {
        return new Promise((resolve, reject) => { 
            fs.createReadStream(file)
            .pipe(csv.parse({from_line: 6, to_line: 7, columns: true, bom: true}, (err, data) => {
                if (err) {
                    reject(err);
                } else {
                    resolve(data[0]);
                }
            }));
        })
    }
    
    async function testGetMap() {
        try { 
            const map = await getMap("./map-input.csv");
            console.log("testGetMap: map:")
            console.table(map);
        } catch (error) { 
            console.error("testGetMap: An error occurred:", error);
        }
    }
    
    testGetMap();
    

    map-input.csv

    <metadata>
    <metadata>
    <metadata>
    <metadata>
    ID,1,2,3,4,5,6,...
    Name,ABC,BCD,CDE,DEF,EFG,FGH
    Val,123,234,345,456,567,678
    

    The output looks like so:

    {
      Name: 'Val',
      ABC: '123',
      BCD: '234',
      CDE: '345',
      DEF: '456',
      EFG: '567',
      FGH: '678'
    }