Returning dictionary created from CSV parser

208 Views Asked by At

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.

1

There are 1 best solutions below

0
On BEST ANSWER

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'
}