【问题标题】:How to condense and remap data of array in Javascript如何在Javascript中压缩和重新映射数组的数据
【发布时间】:2020-06-17 01:56:43
【问题描述】:

我有这个数据数组,需要一个重新映射的版本来遍历日期。

var objArr = [
     {"Country": "US", "2017-07-12": "1", "2017-07-13": "2"},
     {"Country": "US", "2017-07-12": "2", "2017-07-13": "2"},
     {"Country": "CN",  "2017-07-12": "5", "2017-07-13": "7"},
     {"Country": "CN", "2017-07-12": "5", "2017-07-13": "7"}
   ]
  • 国家/地区应将它们的值相加,并且不应在内部数组中出现两次。
  • 最后我想要一个这样的数组:
     var remapped = [
       {"2017-07-12": [
                    {"Country: "US", "value": 3}, 
                    {"Country: "CN", "value": 10}],
       {"2017-07-13": [
                    {"Country: "US", "value": 4},
                    {"Country: "US", "value": 14}]
     ]

在我目前的情况下,我明白了,但国家应该减少并且价值相加:

var remapped = [
   {"2017-07-12": [
                {"Country: "US", "value": 1}, 
                {"Country: "US", "value": 2}, 
                {"Country: "CN", "value": 5}],
                {"Country: "CN", "value": 5}
                  ],
   {"2017-07-13": [
                {"Country: "US", "value": 2},
                {"Country: "US", "value": 2},
                {"Country: "US", "value": 7}
                {"Country: "US", "value": 7}
                 ]
 ]

这就是我迄今为止所做的。但对我来说,这似乎过于复杂,我相信有一种更有效的方法可以解决这个问题: 在这种状态下,我将国家重新映射到日期,但不知道如何“减少”它们。我真的需要对数组进行多次迭代吗?

const res = [];
dateArray.forEach(date => (objArr[date] = [])); // I create an array with dates which could contain another array

objArr.forEach(item => {
  dates.forEach(date => {
    res[date].push({
      Country: item['Country'],
      value: item[date],
    });
  });
});

【问题讨论】:

    标签: javascript arrays sorting reduce remap


    【解决方案1】:

    您可以使用reduce 方法执行此操作,并首先将每个日期的值存储在一个对象中,以便您可以按国家/地区对它们进行分组,然后将这些对象转换为数组。

    var data = [
     {"Country": "US", "2017-07-12": "1", "2017-07-13": "2"},
     {"Country": "US", "2017-07-12": "2", "2017-07-13": "2"},
     {"Country": "CN",  "2017-07-12": "5", "2017-07-13": "7"},
     {"Country": "CN", "2017-07-12": "5", "2017-07-13": "7"}
    ]
    
    const result = data.reduce((r, {Country, ...rest}, i) => {
      Object.entries(rest).forEach(([k, v]) => {
        if(!r[k]) r[k] = {}
        if(!r[k][Country]) r[k][Country] = {Country, value: +v}
        else r[k][Country].value += +v
      })
      
      return r;
    }, {})
    
    for(let i in result) {
      result[i] = Object.values(result[i])
    }
    
    console.log(result)

    【讨论】:

    • 这个输出看起来比请求的格式更符合逻辑,但请注意它是不同的。它要求一组单值对象。
    【解决方案2】:

    您可以为对象的引用获取一个辅助对象并迭代给定数据的键/值对。

    var data = [{ Country: "US", "2017-07-12": "1", "2017-07-13": "2" }, { Country: "US", "2017-07-12": "2", "2017-07-13": "2" }, { Country: "CN", "2017-07-12": "5", "2017-07-13": "7" }, { Country: "CN", "2017-07-12": "5", "2017-07-13": "7" }],
        reference = {},
        result = data.reduce((r, { Country, ...o }) => {
            Object.entries(o).forEach(([k, v]) => {
                if (!reference[k]) {
                    reference[k] = { _: [] };
                    r.push({ [k]: reference[k]._ });
                }
                if (!reference[k][Country]) {
                    reference[k]._.push(reference[k][Country] = { Country, value: 0 });
                }
                reference[k][Country].value += +v;
            });
            return r;
        }, []);
    
    console.log(result);
    .as-console-wrapper { max-height: 100% !important; top: 0; }

    【讨论】:

      【解决方案3】:

      这是另一种方法:

      const extractDates = objArr => Object .entries (objArr .reduce (
        (a, {Country, ...rest}) => Object .entries (rest) .reduce ((a, [date, val]) => ({
          ...a,
          [date]: {...a [date], [Country]: ((a [date] || {}) [Country] || 0) + Number (val)}
        }), a),
        {}
      )) .map (([d, o]) => ({[d]: Object .entries (o) .map (([k, v]) => ({Country: k, value: v}))}))
      
      const objArr = [{"Country": "US", "2017-07-12": "1", "2017-07-13": "2"}, {"Country": "US", "2017-07-12": "2", "2017-07-13": "2"}, {"Country": "CN",  "2017-07-12": "5", "2017-07-13": "7"}, {"Country": "CN", "2017-07-12": "5", "2017-07-13": "7"}]
      
      console .log (extractDates (objArr))
      .as-console-wrapper {max-height: 100% !important; top: 0}

      这给出了您在问题中要求的结果,一个单键元素数组。但请注意,它是围绕这个核心构建的:

      objArr .reduce (
        (a, {Country, ... rest}) => Object .entries (rest) .reduce ((a, [date, val]) => ({
          ...a,
          [date]: {... a [date], [Country]: ((a [date] || {}) [Country] || 0) + Number (val)} 
        }), a),
        {}
      )
      

      这给了我一个更有用的数据结构:

      {
        "2017-07-12": {CN: 10, US: 3}, 
        "2017-07-13": {CN: 14, US: 4}
      }
      

      虽然最终结构(没有Object .entries (...) .map (...) 包装器)可以一次性构建(参见例如 Nina 的回答;来自 Nenand Vracar 的结构略有不同,但我发现这种分解更清晰,并认为在大多数情况下,中间格式会更容易使用。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2022-01-19
        • 2011-09-05
        • 1970-01-01
        • 2022-01-02
        • 1970-01-01
        • 2011-01-21
        • 2019-06-15
        • 2014-03-27
        相关资源
        最近更新 更多