使用多样化的&创建CSV大数据

时间:2016-02-22 14:11:01

标签: javascript csv lodash

我知道创建CSV文件的过程,所以我的问题更具体到我拥有的数据。我有一些录像机,每个都有一些数据。每个数据都包含值和时间戳。所以录音机看起来像这样:

'recorder_name': {
    samples: [{v: 19, t: new Date()}]
}

问题是并非所有记录器都具有所有时间戳的值,并且它们没有相同数量的数据。我开始玩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;
}

所以,我尝试获取所有可用的时间戳,然后只保留唯一的时间戳。问题是如何获取每个时间戳的值。 find函数需要花费很多时间,因为每个记录器平均有500-600个数据点。我从未见过函数执行到最后,因为浏览器选项卡会在很短的时间后死掉。

由于

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

_.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应如下所示:

Date         recorder_a    recorder_b
2015-02-03       10            11
2015-02-04       15             -

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

1 个答案:

答案 0 :(得分:1)

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

// 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);
}

DEMO