【问题标题】:How to create a new array using the data from the old one?如何使用旧数组中的数据创建新数组?
【发布时间】:2016-03-23 12:55:21
【问题描述】:

我想知道,是否可以从给定的 json 数据创建,例如:

data0 = [ {id: name1, value1: 5, value2: 13}, {id: name2, value1: 2, value2: 5}, {id: name3, value1: 4, value2: 6}, {id: name4, value1: 3, value2: 7} ];

下面的数组,还有两个对象,例如:

var data = [ {id: sum1, value: 14}, {id: name1_, value: 8}, {id: name2_, value: 3 }, {id: name3_, value: 2}, {id: name4_, value: 4} {id: sum2, value: 31];

第一个和最后一个对象的值分别等于所有 value1 和 value2 的总和。并且所有其他对象在 value2 和 value1 之间都有一个 value = 差异。

data0 可以具有不同的对象属性值,具体取决于报告的类型。

我在 Microstrategy 中使用的 d3 瀑布图需要它。因此,我不必对 js 代码进行大量更改,只需添加代码以创建新数组,并使用其中的数据构建可视化。

我拥有的csv格式的初始数据0:

id,value1,value2
name1,5,13
name2,2,5
name3,4,6
name4,3,7

据我了解,函数 d3.csv 像 json 数据一样读取 csv 格式的数据,将标题(第一行)作为 4 个对象(在本例中)的属性,其中每一行都包含值每个对象的属性。

我使用以下代码调用数据集函数:

d3.csv("data0.csv", function(error, data) {
var values = d3.keys(data[0]).filter(function(key) {return key !== "id";});

data.forEach(function(d) {
for (var i = 0; i < values.length; i++) {
d.value = +d[values[i]];
return d;
}});

考虑到属性名称也可以不同(不是“value1”和“value2”),我想如何引用所有 value1 和 value2,并找到每个总和。我应该对 i 和 j 使用 for 循环吗?

任何帮助将不胜感激!

【问题讨论】:

  • 这当然是可能的,并且可以通过许多不同的方式实现。是否允许对原始数组进行变异(更改)还是必须是副本?
  • 最好问一个新问题,因为重组与csv数据无关。另外,请看这里:stackoverflow.com/help/someone-answers
  • 你能提供你正在阅读的 csv(s) 吗?
  • @TobyFlemming,我刚刚添加到问题中,我正在阅读的 csv 文件是什么样的。但是,它可以具有任何其他属性名称,具体取决于稍后在 Microstrategy 中生成的报告。

标签: javascript arrays d3.js


【解决方案1】:

不确定您的 id 是什么,因为看起来您正在使用变量。在这种情况下,我将它们转换为字符串。享受吧!

代码本来可以很紧凑,但我认为这会让你将来更容易阅读。如有任何其他问题,请随时提出,乐于提供帮助!

var data = [ 
  {
    id: 'name1', 
    value1: 5, 
    value2: 13
  }, 
  {
    id: 'name2', 
    value1: 2, 
    value2: 5
  }, 
  {
   id: 'name3', 
   value1: 4, 
   value2: 6
  }, 
  {
    id: 'name4', 
    value1: 3, 
    value2: 7
  } 
];

// Calculate sums
var value1Sum = 0;
var value2Sum = 0;

data.forEach(function(object) {
  value1Sum += object.value1;
  value2Sum += object.value2;
});

// Insert sums at front and back
data.unshift({
  id: 'sum1',
  value: value1Sum
});

data.push({
  id: 'sum2',
  value: value2Sum
});

// Calculate differences
data = data.map(function(object, idx) {
  if (idx === 0 || idx === data.length - 1) {
    return object;
  }
  
  return {
    id: object.id + '_',
    value: object.value2 - object.value1
  };
});

【讨论】:

  • 感谢您的回答! :) 我对问题进行了一些编辑,你能看一下吗?
  • 现在看看:)
【解决方案2】:

基本上你可以用Array#map()来完成这个任务。

var data0 = [{ id: 'name1', value1: 5, value2: 13 }, { id: 'name2', value1: 2, value2: 5 }, { id: 'name3', value1: 4, value2: 6 }, { id: 'name4', value1: 3, value2: 7 }],
    result = function (array) {
        var sum1 = 0,
            sum2 = 0,
            r = array.map(function (a) {
                sum1 += a.value1;
                sum2 += a.value2;
                return { id: '_' + a.id, value: a.value2 - a.value1 };
            });
        return [{ id: 'sum1', value: sum1 }].concat(r, { id: 'sum2', value: sum2 });
    }(data0);

document.write('<pre>' + JSON.stringify(result, 0, 4) + '</pre>');

【讨论】:

  • 感谢您的回答,@Nina! :) 我已经对问题进行了一些编辑,也许您知道在这种情况下如何创建新数组?
  • 最好问一个新问题,因为重组与csv数据无关。另外,请看这里:stackoverflow.com/help/someone-answers
【解决方案3】:
data0 = [ {id: name1, value1: 5, value2: 13}, {id: name2, value1: 2, value2: 5}, {id: name3, value1: 4, value2: 6}, {id: name4, value1: 3, value2: 7} ];
var data = [];
var sum1 = 0;
var sum2 = 0; 
for (i = 0; i < data0.length; i++) {
  sum1 += data0[i].value1;
  sum2 += data0[i].value2;
  var diff = data0[i].value2 - data0[i].value1;
  data.push({id: 'name' + (i+1) + '_', value: diff});
}
data.unshift({id: 'sum1', value: sum1});
data.push({id: 'sum2', value: sum2});

Array.push() 在数组的最后一个 Item 之后添加,Array.unshift() 在第一个 Item 之前添加。

【讨论】:

  • 谢谢@Marius,我已经对问题进行了一些编辑,如果您能看一下,将不胜感激。
【解决方案4】:

有许多不同的方法可以达到您需要的结果。其中之一是在数组项上使用mapreduce 函数。你可以阅读更多关于mapreduceon MDN的信息。

var  data0 = [ {id: 'name1', value1: 5, value2: 13}, {id: 'name2', value1: 2, value2: 5}, {id: 'name3', value1: 4, value2: 6}, {id: 'name4', value1: 3, value2: 7} ];

// calculate `sum1` and `sum2` as the sums of `value1` and `value2` respectively
var sums = data0.reduce(function (sums, item) {
    sums.sum1.value += item.value1;
    sums.sum2.value += item.value2;
    return sums;
}, {
    sum1: {id: 'sum1', value: 0},
    sum2: {id: 'sum2', value: 0}
});

// transform (map) the existing data and calculate `value` as a difference between `value2` and `value1`
var restOfData = data0.map(function (item) {
    return {
        id: item.id,
        value: item.value2 - item.value1
    };
});

// merge the obtained results into a single array
var data = [sums.sum1].concat(restOfData, [sums.sum2]);

document.write(JSON.stringify(data));

如果您使用 ES2015,由于箭头函数和展开运算符,这段代码的可读性会更高:http://codepen.io/mmiszy/pen/EKmmEy?editors=0010

【讨论】:

  • 感谢您的回答! :) 我对问题进行了一些编辑,你能看一下吗?
  • 你至少应该解释一下你的代码是做什么的。
  • @RostyslavaRomaniuk 您应该接受其中一个答案并创建一个新问题,因为您现在描述的是一个完全不同的问题stackoverflow.com/help/someone-answers
猜你喜欢
  • 2019-10-07
  • 1970-01-01
  • 1970-01-01
  • 2016-02-04
  • 2021-04-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-02-29
相关资源
最近更新 更多