如何在 Javascript 中压缩和重新映射数组数据

How to condense and remap data of array in Javascript

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

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}
                 ]
 ]

这就是我到目前为止的内容。但对我来说,这似乎过于复杂,而且我相信有一种更有效的方法可以解决这个问题: 在这种情况下,我已将国家/地区重新映射到日期中,但不确定如何 "reduce" 它们。我真的必须对数组进行多次迭代吗?

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],
    });
  });
});

您可以使用 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)

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

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

这是另一种方法:

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 的结构略有不同,但我发现这种分解更清晰,并认为中间格式在大多数情况下更易于使用。