将一个包含多个字典的列表用Javascript转换为一个字典,其中字典的值为原列表中所有字典对应键的值所组成的列表。

4

是否有一个内置的JavaScript函数可以转换字典列表

const L = 
      [ { "day": "20201210", "count": "100" } 
      , { "day": "20201211", "count": "120" } 
      , { "day": "20201212", "count":  "90" } 
      , { "day": "20201213", "count": "150" } 
      ] 

把它转换成一个像这样的列表字典:
const D = 
      { "day"   : [ "20201210", "20201211", "20201212", "20201213"] 
      , "count" : [ "100", "120", "90", "150"] 
      } 

在JS中是否有最简单的方法实现这个操作?(这有点类似于矩阵“转置”操作)。

注意:这里是一个转置而不是类似于在对象数组上进行分组的最有效方法那样的分组。


这个回答解决了你的问题吗?按多个值分组Underscore.JS但保留键和值 - AZ_
1
这个问题应该重新开放。这甚至与数组元素的分组无关。第二个链接的问题是相关的,但仍然不同到足以证明需要一个新的问题。 - lex82
我修改了我的答案,使其适用于一个未知的键列表。 - Mister Jojo
我修改了我的答案,使其成为一个通用函数,符合你矩阵函数的思路。 - Mister Jojo
我改变了我的答案,使它更快(比这里的任何人都快)。 - Mister Jojo
6个回答

2
假设所有对象都具有相同的键,并且您的数组不为空,则以下代码可行:
let D = {};
Object.keys(L[0]).forEach(k => {
    D[k] = L.map(o => o[k]);
});

当然有更加高效的解决方案,但这个方法简短明了,在效率上也不算太差。


2
这是一个相对简短且高效的通用数值方法。
L.forEach(o => {
  Object.keys(o).forEach(k => {
    D[k] ||= [];
    D[k].push(o[k]);
  });
});

const L = [{
  "day": "20201210",
  "count": "100"
}, {
  "day": "20201211",
  "count": "120"
}, {
  "day": "20201212",
  "count": "90"
}, {
  "day": "20201213",
  "count": "150"
}]

let D = {};

L.forEach(o => {
  Object.keys(o).forEach(k => {
    D[k] ||= [];
    D[k].push(o[k]);
  });
});

console.log(D);


1
map() 会产生新的数组,但你并不需要它。使用 forEach() 更好,因为你只关心副作用。 - lex82

1
你可以将字典数组重新结构化,然后使用Array.prototype.map重新映射它。
例如(以下操作需要使用map N * X次迭代元素,其中N是L的长度,X是D中所需属性的数量。如果你有许多属性要监视,请忽略此提示。)

But, this is the easiest readable approach that I'd want to introduce to you before the 2nd approach.

const L = [{"day":"20201210","count":"100"},{"day":"20201211","count":"120"},{"day":"20201212","count":"90"},{"day":"20201213","count":"150"}];

const D = {
  'day': L.map(elem => elem['day']),
  'count': L.map(elem => elem['count']),
};

console.log(D);

我建议另一种方法是使用Array.prototype.reduce,在你的情况下这是最好的选择,因为它可以通过向初始数组添加更多属性来轻松扩展。

const L = [{"day":"20201210","count":"100"},{"day":"20201211","count":"120"},{"day":"20201212","count":"90"},{"day":"20201213","count":"150"}];

const D = L.reduce((acc, cv) => {
  for (const propertyToGrab in acc) {
    if (cv.hasOwnProperty(propertyToGrab)) {
      acc[propertyToGrab].push(cv[propertyToGrab]);
    }
  }

   return acc;
}, {
  'day': [],
  'count': []
});

console.log(D);


1

我认为在原生JavaScript中没有这样的函数。

一个简单、纯净且易于理解的方法是这样的:

var L = [
    {
        "day": "20201210",
        "count": "100"
    },
    {
        "day": "20201211",
        "count": "120"
    },
    {
        "day": "20201212",
        "count": "90"
    },
    {
        "day": "20201213",
        "count": "150"
    }
];
var D = { };

for (var dict in L)
{
    for (var key in L[dict]) 
    {
        if (D[key] == null) {
            D[key] = [ ];
        }
        
        D[key].push(L[dict][key]);
    }
} 

这绝不是最简洁或最优化的方法,但它可以正常工作。

0
const D={day:[], count:[]};

    for(const item of L){
    D.day.push(item.day);
    D.count.push(item.count);
    }

0
 const input = [{"day":"20201210","count":"100"},{"day":"20201211","count":"120"},{"day":"20201212","count":"90"},{"day":"20201213","count":"150"}];
 // Create a variable that will store the result
 let result = {};
 // Loop through the input with forEach
 input.forEach((element) => {
     // Loop through the keys 
    for(let key in element) {
        // Check if a key is not exist in the result 
        if(!result.hasOwnProperty(key)) {
            // Then create an key and assign an empty array to it
            result[key] = [];
        }
        // Push the elemnts to the array.
        result[key].push(element[key]);
    }
 });

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接