从节点中的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); }); }); });
我知道我的一个问题是我很快将模型推到数组中,导致下面的表单的最终数组,其中model1
被model2
覆盖
[ { 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将此逻辑添加到您的代码中。