从节点中的parsing的csv文件构build对象数组

我有多个表单的CSV文件

  • model1A
  • model1B
  • model2A
  • model2B

其中每个csv是一个数组即model1A = [1, 1, 1]

我想parsing这些csvs并创build一个包含所有这些模型的数组,其中数组中的每个元素都是一个对应于一个特定模型的对象,即

 finalArray = [ { "model" : "model1", "A" : [1, 1, 1], "B" : [2, 2, 2] }, { "model" : "model2", "A" : [3, 3, 3], "B" : [4, 4, 4] } ] 

我到目前为止的代码是

 var csv = require('csv'); var fs = require('fs'); var parser = csv.parse(); var util = require('util'); var junk = require('junk'); var _ = require('lodash'); var models = []; fs.readdir(__dirname+'/data', function(err, files) { var model = {}; _.forEach(files, function(n, key) { console.log('Analysing file: ' + n); var modelName; var modelNum; var modelParam; modelNum = n.match(/\d+/)[0]; modelName = 'model' + modelNum; modelParam = (n.substring(0, n.indexOf('.'))).replace(modelName,''); model.model = modelName; model[modelParam] = []; models.push(model); //if (Object.keys(model).length === 3) { // models.push(model); // model = {}; //} fs.createReadStream(__dirname+'/data/'+n).pipe(csv.parse()).pipe(csv.transform(function(row) { model[modelParam].push(row); })).on('readable', function(){ while(this.read()){} }).on('end', function() { console.log('finished reading file ' + n); if (key === (files.length - 1)) { fs.writeFile('result.json', JSON.stringify(models), function (err) { if (err) throw err; console.log(models.length + ' model(s) parsed'); console.log('done'); }); } }).on('error', function(error) { console.log(error); }); }); }); 

我知道我的一个问题是我很快将模型推到数组中,导致下面的表单的最终数组,其中model1model2覆盖

 [ { model: 'model2', A: [], B: [] }, { model: 'model2', A: [], B: [] }, { model: 'model2', A: [], B: [] }, { model: 'model2', A: [], B: [] } ] 

这就是为什么我尝试这个代码

 if (Object.keys(model).length === 3) { models.push(model); model = {}; } 

但当然这不能工作,因为fs.createReadStream是asynchronous的,我正在清除model = {} ,才能正常运行。

我现在正处于现在的阶段,我觉得自己在圈子里散散步,让事情变得更糟。 我想创build一个更通用的东西,但是,现在我很乐意为它在这里提出的案例工作,然后我可以看看改进它。

任何帮助将非常感激!


更新1

遵循saquib khan提出的在循环内部移动var model = {}的build议使我更接近我的目标,但仍然不正确。 以下是目前的结果

 [ { "model": "model1", "A": [ [ "1" ], [ "2" ], [ "3" ], [ "4" ] ] }, { "model": "model1", "B": [ [ "1" ], [ "2" ], [ "3" ], [ "4" ] ] }, { "model": "model2", "A": [ [ "1" ], [ "2" ], [ "3" ], [ "4" ] ] }, { "model": "model2", "B": [ [ "1" ], [ "2" ], [ "3" ], [ "4" ] ] } ] 

更新2

Denys Denysiuk的build议也是如此,结果更接近我想要的,但仍然很短

 [ { "model": "model1", "A": [ "1", "2", "3", "4" ] }, { "model": "model1", "B": [ "1", "2", "3", "4" ] }, { "model": "model2", "A": [ "1", "2", "3", "4" ] }, { "model": "model2", "B": [ "1", "2", "3", "4" ] } ] 

这将工作,如果我能以某种方式迭代最后的数组对象,合并对象与匹配的model名称。 我目前正在浏览lodash文档 ,看看能否找出答案 。 如果我这样做,我会回到这里。

试试这个:

 fs.readdir(__dirname+'/data', function(err, files) { _.forEach(files, function(n, key) { console.log('Analysing file: ' + n); var modelNum = n.match(/\d+/)[0]; var modelName = 'model' + modelNum; var modelParam = (n.substring(0, n.indexOf('.'))).replace(modelName,''); var model = {}; var isNewModel = true; for(var i = 0; i < models.length; i++) { if(models[i].model == modelName) { model = models[i]; isNewModel = false; break; } } if(isNewModel) { model.model = modelName; models.push(model); } model[modelParam] = []; fs.createReadStream(__dirname+'/data/'+n).pipe(csv.parse()).pipe(csv.transform(function(row) { model[modelParam].push(row[0]); })).on('readable', function(){ while(this.read()){} }).on('end', function() { console.log('finished reading file ' + n); if (key === (files.length - 1)) { fs.writeFile('result.json', JSON.stringify(models), function (err) { if (err) throw err; console.log(models.length + ' model(s) parsed'); console.log('done'); }); } }).on('error', function(error) { console.log(error); }); }); 

代码中有一个非常小的编码错误。

var model = {}; 应该在里面forEach循环。

尝试下面的代码:

 var csv = require('csv'); var fs = require('fs'); var parser = csv.parse(); var util = require('util'); var junk = require('junk'); var _ = require('lodash'); var models = []; fs.readdir(__dirname+'/data', function(err, files) { _.forEach(files, function(n, key) { console.log('Analysing file: ' + n); var model = {}; var modelName; var modelNum; var modelParam; modelNum = n.match(/\d+/)[0]; modelName = 'model' + modelNum; modelParam = (n.substring(0, n.indexOf('.'))).replace(modelName,''); model.model = modelName; model[modelParam] = []; models.push(model); //if (Object.keys(model).length === 3) { // models.push(model); // model = {}; //} fs.createReadStream(__dirname+'/data/'+n).pipe(csv.parse()).pipe(csv.transform(function(row) { model[modelParam].push(row); })).on('readable', function(){ while(this.read()){} }).on('end', function() { console.log('finished reading file ' + n); if (key === (files.length - 1)) { fs.writeFile('result.json', JSON.stringify(models), function (err) { if (err) throw err; console.log(models.length + ' model(s) parsed'); console.log('done'); }); } }).on('error', function(error) { console.log(error); }); }); }); 

Node.js是事件驱动的,所以也许你可以使用事件模块来build立你的代码: https : //nodejs.org/api/events.html

你的问题似乎是你重写之前的数组中的条目,所以也许你应该去下一步(阅读另一个CSV?)只有当前一个完成写所需的一切。

您可以使用Event将此逻辑添加到您的代码中。