Javascript 创建具有多样性的CSV&;大数据

Javascript 创建具有多样性的CSV&;大数据,javascript,csv,lodash,Javascript,Csv,Lodash,我知道创建CSV文件的过程,因此我的问题更具体到我拥有的数据。我有一些录音机,每个都有一些数据。每个数据由值和时间戳组成。录音机是这样的: 'recorder_name': { samples: [{v: 19, t: new Date()}] } Date recorder_a recorder_b 2015-02-03 10 11 2015-02-04 15 - 问题在于并非所有记录器都具

我知道创建CSV文件的过程,因此我的问题更具体到我拥有的数据。我有一些录音机,每个都有一些数据。每个数据由值和时间戳组成。录音机是这样的:

'recorder_name': {
    samples: [{v: 19, t: new Date()}]
}
Date         recorder_a    recorder_b
2015-02-03       10            11
2015-02-04       15             -
问题在于并非所有记录器都具有所有时间戳的值,并且它们的数据量也不相同。我开始玩
lodash
,但它真的很慢。到目前为止,我掌握的情况如下:

function createCSVRows(data) {
    const timestamps = [];
    const csvRows = [];

    //data contains all recorders
    _.forEach(data, ({samples}) => {
        _.forEach(samples, s => {
            const timestamp = moment(s.t).utc();
            timestamps.push(timestamp.format('YYYY-MM-DD HH:mm:ss'));
        });
    });

    _(timestamps)
        .uniq()
        .sortBy(t => moment(t).utc())
        .forEach(t => {
            const csvRow = [t];

            _.forEach(data, ({samples}) => {
                const value = _.find(samples, s => moment(s.t).utc().format('YYYY-MM-DD HH:mm:ss') === t);

                if(!value) {
                    csvRow.push('');
                } else {
                    csvRow.push(value.v);
                }
            });
            csvRows.push(csvRow);
        })
        .value();

    return csvRows;
}
_.forEach(data, ({samples}) => {
    _.forEach(samples, s => {
        const timestamp = moment(s.t).utc().format('YYYY-MM-DD HH:mm:ss');
        if(!timestamps[timestamp]) {
            timestamps[timestamp] = [];
        }

        _.forEach(timestamps, (v, t) => {
            if(t === timestamp) {
                v.push(s.v);
            } else {
                v.push('');
            }
        });
    });
});
因此,我尝试获取所有可用的时间戳,然后只保留唯一的时间戳。问题是如何获得每个时间戳的值。
find
功能需要很多时间,因为每个记录器平均有500-600个数据点。我从未见过函数执行到最后,因为浏览器选项卡在短时间后消失

谢谢

编辑:根据@charlietfl的评论,我还尝试了以下方法:

function createCSVRows(data) {
    const timestamps = [];
    const csvRows = [];

    //data contains all recorders
    _.forEach(data, ({samples}) => {
        _.forEach(samples, s => {
            const timestamp = moment(s.t).utc();
            timestamps.push(timestamp.format('YYYY-MM-DD HH:mm:ss'));
        });
    });

    _(timestamps)
        .uniq()
        .sortBy(t => moment(t).utc())
        .forEach(t => {
            const csvRow = [t];

            _.forEach(data, ({samples}) => {
                const value = _.find(samples, s => moment(s.t).utc().format('YYYY-MM-DD HH:mm:ss') === t);

                if(!value) {
                    csvRow.push('');
                } else {
                    csvRow.push(value.v);
                }
            });
            csvRows.push(csvRow);
        })
        .value();

    return csvRows;
}
_.forEach(data, ({samples}) => {
    _.forEach(samples, s => {
        const timestamp = moment(s.t).utc().format('YYYY-MM-DD HH:mm:ss');
        if(!timestamps[timestamp]) {
            timestamps[timestamp] = [];
        }

        _.forEach(timestamps, (v, t) => {
            if(t === timestamp) {
                v.push(s.v);
            } else {
                v.push('');
            }
        });
    });
});
问题是我必须循环时间戳,因为我必须用空值填充所有其他时间戳。这个标签还没用完。有什么想法吗

编辑2: 样本数据:

{
   'recorder_a': {
       samples: [{t: new Date(2015,02,03), v: 10}, {t: new Date(2015,02,04), v: 15}]
    },
   'recorder_b': {
       samples: [{t: new Date(2015,02,03), v: 11}] 
    }
}
预期的CSV应该如下所示:

'recorder_name': {
    samples: [{v: 19, t: new Date()}]
}
Date         recorder_a    recorder_b
2015-02-03       10            11
2015-02-04       15             -

我的意思是,如果记录器没有时间戳的值,那么我必须显示一个空shell。

这里有一种方法应该可以工作。使用对象而不是数组来减少循环中大量的数组搜索

// object to store dates as keys
var dates = {} // {'2015-12-22':{recorder_a:4, recorder_c:7}}
// array of recorder names
var recorders = Object.keys(data);
// populate dates object with known recorders per date
recorders.forEach(function(recorder) {
  data[recorder].samples.forEach(function(sample) {
    var dateStr = getDateString(sample.t)
    if (!dates[dateStr]) {
      dates[dateStr] = {}
    }
    dates[dateStr][recorder] = sample.v
  });
});
// array of date keys sorted
var datesArr = Object.keys(dates).sort(function(a, b) {
  return new Date(a) - new Date(b);
});

var headings= ['Date'].concat(recorders);
// now fill in missing recorders on each date
var res = [csvRow(headings)];
datesArr.forEach(function(date) {
  var row = [date],
    rowData = dates[date];
  recorders.forEach(function(recorder) {
    var value = rowData.hasOwnProperty(recorder) ? rowData[recorder] : '';
    row.push(value)
  });
  res.push(csvRow(row))
});

// final csv result string 
var csv = res.join('')


// row csv helper
function csvRow(arr){
  return '"'+ arr.join('","')+'"\n'
}
// helper
function getDateString(date) {
  return date.toISOString().slice(0, 10);
}

更有效地创建时间戳为键的对象。迭代一次并检查键是否存在。然后迭代对象以映射回数组。将删除
find()
正在执行的重复数组搜索doing@charlietfl你的意思是不在数组中添加时间戳?你能提供一个小例子吗?是的。。从一开始。若对象不存在,则向其添加时间戳,并将值指定为行。忽略,如果它已经存在,我看到,将测试它,并让你知道由于某种原因,日期排序是不正确的工作各地。必须返回
新日期(a)-新日期(b)
是的…我把它作为一个快速的概念。字符串不是最好的