Javascript 将JSON转换为数组以便在C3中绘制时间序列的更好方法?

Javascript 将JSON转换为数组以便在C3中绘制时间序列的更好方法?,javascript,d3.js,lodash,c3.js,Javascript,D3.js,Lodash,C3.js,我正在将一些JSON数据转换成一种格式,用于在C3中绘制timeseries,它将数组数组作为列输入。我有我唯一的x值数组,但我不能找到一个很好的方法来获得我的y值。一旦我完成了这个,我需要用numSold添加y2,但我想如果我能解决这个问题,我就能够解决这个问题 这是我需要的数据的最终格式: [ ["x", "9-2-17", "9-4-17", "10-2-17"], ['item1-cost', 100, 150, 10], ['item3-cost', 200, null,

我正在将一些JSON数据转换成一种格式,用于在C3中绘制timeseries,它将数组数组作为列输入。我有我唯一的x值数组,但我不能找到一个很好的方法来获得我的y值。一旦我完成了这个,我需要用numSold添加y2,但我想如果我能解决这个问题,我就能够解决这个问题

这是我需要的数据的最终格式:

[
  ["x", "9-2-17", "9-4-17", "10-2-17"],
  ['item1-cost', 100, 150, 10],
  ['item3-cost', 200, null, 20],
  ...
]
没有设置日期数或项目数。这是我从数据库里读到的。项目编号不一定是连续的。我们只关心为我们有数据的项目绘制数据图。但不会有每个日期项目组合的数据。当这种情况发生时,我需要插入一个空值来指示该项没有该日期的数据。项目编号为1-索引

除了简单的JavaScript函数之外,我还可以使用lo dash或D3中的任何东西来解决这个问题,但我正试图避免难以阅读的代码和低效的代码。我觉得其他人一定需要这个,我应该使用一些函数,比如过滤函数

我当前的实现没有我希望的那么高效,而且有点难以理解。我使用项目编号作为索引,并生成一个稀疏数组,稍后将进行压缩。以下是psudocode:

For every d object in data
  For the i index of d.date in uniqueDates
    If values[d.item] is undefined
      Fill values[d.item]] with null for uniqueDates.length
    Set values[d.item][i] to d.cost
Convert values to dense format for graphing
下面是我正在玩的小提琴的链接:

var数据=[
{日期:'9-2-17',项目:1,费用:100},
{日期:'9-2-17',项目:3,费用:200},
{日期:'9-4-17',项目:1,费用:150},
/*“9-4-17”没有第3项的条目,因此成本应计为空*/
{日期:'10-2-17',项目:1,费用:10},
{日期:'10-2-17',项目:3,费用:20}
]
var uniqueDates=uq.uniq(q.flatMap(数据,'date'));
唯一日期。取消移位('x');
var值=[];
值。推送(唯一日期);
函数getLabel(索引){
返回“项目”+索引+“-”+“成本”;
}
对于(var d=0;d
我对这个问题很感兴趣,并提出了第一个版本。它和你的有点不同,但在这里。我会注意到,我没有尝试对日期进行排序或将项目重命名为有用的内容,但可以添加这些内容

var数据=[
{日期:'9-2-17',项目:1,费用:100},
{日期:'9-2-17',项目:3,费用:200},
{日期:'9-4-17',项目:1,费用:150},
/*“9-4-17”没有第3项的条目,因此成本应计为空*/
{日期:'10-2-17',项目:1,费用:10},
{日期:'10-2-17',项目:3,费用:20},
{日期:'10-3-17',项目:2,费用:2000}
]
//效用函数
常数乘积=(…集合)=>
集合。减少((acc,集合)=>
_.flant(acc.map(x=>set.map(y=>[…x,y])),
[[]]);
//肉和土豆
const builder=lookup=>pairs=>pairs.reduce((agg,[item,date])=>{
const out=u.cloneDeep(agg);
const value=u.get(查找,[date,item,'cost'],null);
const evalue=uu.get(out,date,[]);
评估推送(值);
_.设定(出发日期、评估值);
返回;
}, {})
//设置用于搜索的数据结构
const byDateByItem=u.mapValues(u.groupBy(数据,'date'),x=>DateBy(x,'item'));
const items=uq.uniq(data.map(x=>x.item));
const dates=uq.uniq(data.map(x=>x.date));
//创建所有可能性
常数对=产品(项目、日期);
//用值填充可能性
const hash=builder(byDateByItem)(成对);
//将具有值的键放在各自的列表中
常量p=u.toPairs(hash.map)(u.flatte);
//将数据粉碎成矩阵类型的东西
常数表=['x',…项],…p];
//把桌子翻过来(╯°□°)╯︵ ┻━┻
const out=uzy.zip(…表);
console.log('out',out);

注意,从稀疏到密集的转换不是完全必要的;我们可以用空数组填充:嘿,这很酷。我想知道对于大量数据来说,它的性能如何。最初的jsperf.com结果与我最初的实现一样快,但如果数组很大,我不确定这是否成立。我打赌不是blazing fast,但是如果您想要blazing fast perf,您很可能不会使用JS。大多数情况下,在需要对代码进行微优化之前,您将能够更改其他内容。您可能会拉出
cloneDeep
部分以快速节省一些时间,但编写此代码是为了最大限度地提高可维护性和性能速度太快了。
var data = [
  {date: '9-2-17', item: 1, cost: 100},
  {date: '9-2-17', item: 3, cost: 200},
  {date: '9-4-17', item: 1, cost: 150},
  /* '9-4-17' does not have an entry for item 3 so cost should be counted as null */
  {date: '10-2-17', item: 1, cost: 10},
  {date: '10-2-17', item: 3, cost: 20}
]

var uniqueDates = _.uniq(_.flatMap(data, 'date'));
uniqueDates.unshift('x');

var values = [];
values.push(uniqueDates);

function getLabel(index) {
  return 'item' + index + '-' + 'cost';
}

for (var d = 0; d < data.length; d++) {
  var i = _.indexOf(uniqueDates, data[d].date);
  if (data[d].item !== undefined) {
    var item = data[d].item;
    if (values[item] === undefined) {
        values[item] = _.fill(Array(uniqueDates.length), null);
        values[item][0] = getLabel(item);
    }
    values[item][i] = data[d].cost;
    }
}

function checkIfUndefined(x) {
    return (x !== undefined);
}

function sparseToDense(data) {
  return data.filter(checkIfUndefined);
}

values = sparseToDense(values);