【问题标题】:Array transformation in D3D3 中的数组转换
【发布时间】:2016-04-12 04:39:08
【问题描述】:

从中转换数组的最佳方法是什么

[{
  "state": "vic",
  "age_group_1": 10,
  "age_group_2": 20,
  "age_group_3": 30,
  "age_group_4": 40,
  "age_group_5": 50,
}, {
  "state": "nsw",
  "age_group_1": 60,
  "age_group_2": 70,
  "age_group_3": 80,
  "age_group_4": 90,
  "age_group_5": 100,
}, {
  "state": "tas",
  "age_group_1": 11,
  "age_group_2": 21,
  "age_group_3": 31,
  "age_group_4": 41,
  "age_group_5": 51,
}, {
  "state": "qld",
  "age_group_1": 61,
  "age_group_2": 71,
  "age_group_3": 81,
  "age_group_4": 91,
  "age_group_5": 101,
}]

到这里

[{
  "age_group": "age_group_1",
  "states": [{
    "name": "vic",
    "value": 10
  }, {
    "name": "nsw",
    "value": 60
  }, {
    "name": "tas",
    "value": 11
  }, {
    "name": "qld",
    "value": 61
  }]
}, {
  "age_group": "age_group_2",
  "states": [{
    "name": "vic",
    "value": 20
  }, {
    "name": "nsw",
    "value": 70
  }, {
    "name": "tas",
    "value": 21
  }, {
    "name": "qld",
    "value": 71
  }]
}, {
  "age_group": "age_group_3",
  "states": [{
    "name": "vic",
    "value": 30
  }, {
    "name": "nsw",
    "value": 80
  }, {
    "name": "tas",
    "value": 31
  }, {
    "name": "qld",
    "value": 81
  }]
}, {
  "age_group": "age_group_5",
  "states": [{
    "name": "vic",
    "value": 40
  }, {
    "name": "nsw",
    "value": 90
  }, {
    "name": "tas",
    "value": 41
  }, {
    "name": "qld",
    "value": 91
  }]
}, {
  "age_group": "age_group_5",
  "states": [{
    "name": "vic",
    "value": 50
  }, {
    "name": "nsw",
    "value": 100
  }, {
    "name": "tas",
    "value": 51
  }, {
    "name": "qld",
    "value": 101
  }]
}]

我可以使用简单的 javascript 和循环,但我想使用 d3 函数或任何其他处理数据转换的库

哪个是数据转换的最佳库。

【问题讨论】:

  • “纯 Javascript”。既然 JS 已经内置于语言中,你为什么还要使用 D3?
  • 道歉@Mike'Pomax'Kamermans!误读了问题。我同意你使用纯 JS 进行转换然后将其提供给 D3 的观点
  • @Microchip78,您能否分享您可以转换的代码,我们也许可以改进它
  • 每个州的age_groups 是否总是5?

标签: javascript arrays json d3.js


【解决方案1】:

您可以使用临时对象来引用结果数组。

var data = [{ "state": "vic", "age_group_1": 10, "age_group_2": 20, "age_group_3": 30, "age_group_4": 40, "age_group_5": 50, }, { "state": "nsw", "age_group_1": 60, "age_group_2": 70, "age_group_3": 80, "age_group_4": 90, "age_group_5": 100, }, { "state": "tas", "age_group_1": 11, "age_group_2": 21, "age_group_3": 31, "age_group_4": 41, "age_group_5": 51, }, { "state": "qld", "age_group_1": 61, "age_group_2": 71, "age_group_3": 81, "age_group_4": 91, "age_group_5": 101, }],
       result = [];

data.forEach(function (a) {
    Object.keys(a).forEach(function (k) {
        if (k !== 'state') {
            if (!this[k]) {
                this[k] = { age_group: k, states: [] };
                result.push(this[k]);
            }
            this[k].states.push({ name: a.state, value: a[k] });
        }
    }, this);
}, {});

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

【讨论】:

    【解决方案2】:

    利用现代 JS 而不是试图让 D3 做到这一点 - 这是非常简单的代码:

    var basedata = the original array from your question;
    
    // I assume your data already has this array of categories somewhere,
    // but if it doesn't, let's just declare it here:
    var age_groups = [
      "age_group_1",
      "age_group_2",
      "age_group_3",
      "age_group_4",
      "age_group_5"
    ];
    
    var transformed = age_groups.map(group => {
      return {
        age_group: group,
        states: basedata.map(set => {
          return { state: set.state, value: set[group] }
        })
      };
    });
    

    完成了。

    之所以可行,是因为您希望对象锁定在您的年龄段,因此我们首先要确保基于这些对象创建映射。然后,对于每个年龄组,我们只需遍历基础数据并返回状态/值对。没什么复杂的,ES6/ES2015 为我们完成了这项工作。

    不喜欢 ES6/ES2015?与时俱进的好机会,但也很容易重写为旧的 ES5 格式:将每个 (...) =&gt; { ... } 替换为 function(...) { return ... } 并完成。

    【讨论】:

    • 非常感谢 Mike ...这就像一个魅力...我不知道 JS 中存在此功能,因为到目前为止我大多使用 js 来进行 dom 操作...因为我开始探索 d3 我开始在客户端处理数据...
    【解决方案3】:

    你可以试试这样的:

    var data=[{state:"vic",age_group_1:10,age_group_2:20,age_group_3:30,age_group_4:40,age_group_5:50},{state:"nsw",age_group_1:60,age_group_2:70,age_group_3:80,age_group_4:90,age_group_5:100},{state:"tas",age_group_1:11,age_group_2:21,age_group_3:31,age_group_4:41,age_group_5:51},{state:"qld",age_group_1:61,age_group_2:71,age_group_3:81,age_group_4:91,age_group_5:101}];
    
    var _tmp = {}
    var kepReg = /^age_group/;
    data.forEach(function(item) {
      for (var k in item) {
        if (kepReg.test(k)) {
          if (!_tmp[k])
            _tmp[k] = {
              state: []
            };
          _tmp[k].state.push({
            name: item["state"],
            value: item[k]
          })
        }
      }
    });
    
    var result = Object.keys(_tmp).map(function(k) {
      return {
        age_group: k,
        states: _tmp[k].state
      }
    });
    
    document.write("<pre>" + JSON.stringify(result, 0, 4) + "</pre>")

    【讨论】:

    • 使用内置的 Array.map 函数(现在是 JS 的一部分)可以让您在不到 10 行的时间内编写此代码。
    • 我知道这一点,并在其中使用了我的答案。但我的答案需要整个 json 并使用年龄组的值,创建对象。因此,即使添加了任何新值,这也将起作用
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-08-14
    • 1970-01-01
    • 1970-01-01
    • 2013-04-01
    • 1970-01-01
    • 2023-03-27
    相关资源
    最近更新 更多