我可以使用reduce将带有自定义键的数组转换为对象数组,并且还计算重复值吗?

时间:2019-12-16 11:20:58

标签: javascript arrays data-manipulation

在我当前的代码中,我有一个名称数组,这些名称通过reduce()变成一个对象,任何重复的名称都会增加一个计数值。

初始数组(nameArray):

["Name1","Name2","Name2","Name2","Name3","Name4","Name5"]

减少代码:

    const nameCount = nameArray.reduce((a, b) => {
        a[b] = (a[b] || 0) + 1
        return a
    }, {})

减少输出:

{"Name1":1,"Name2":3,"Name3":1,"Name4":1,"Name5":1}

我想将其格式更改为:

[
{
"name": Name1,
"count": 1
},
{
"name": Name2,
"count": 3
},
{
"name": Name3,
"count": 1
}
...etc
]

仅使用reduce可能吗?最好,最有效的方法是什么? 我尝试过更改化简代码,但无法使其正常工作,搜索解决方案也没有结果。

感谢您的帮助!

3 个答案:

答案 0 :(得分:2)

您可以在reduce方法内创建所需的数组,但是效率不高,因为每次您需要通过name搜索以更新计数时都可以。

一种简单的方法是使用Object.keys方法。

var nameArray = ["Name1","Name2","Name2","Name2","Name3","Name4","Name5"]
const nameCount = nameArray.reduce((a, b) => {
    a[b] = (a[b] || 0) + 1
    return a
}, {})
console.log(Object.keys(nameCount).map(key => ({name : key, count: nameCount[key]})));

答案 1 :(得分:1)

如果您只想使用Array.reduce(),请尝试以下操作:

const nameArray = ["Name1", "Name2", "Name2", "Name2", "Name3", "Name4", "Name5"];

const nameCount = nameArray.reduce((ac, a) => {
  const index = ac.findIndex(({ name }) => name === a); 
  if(index > -1) {
    ac[index].count++;
  } else {
    ac.push({ name: a, count: 1 });
  } 
  return ac;
}, [])

console.log(nameCount)

答案 2 :(得分:1)

可以使用reduce来完成。例如:

const nameCount = nameArray.reduce((a, val) => {
  const obj = a.find(x => x.name === val);
  if (obj) {
    obj.count++;
  } else {
    a.push({name: val, count: 1});
  }
  return a
}, []);

什么是“最佳”和“最高效”有待解释。

减速机的每次运行都需要检查重复项。这是通过再次遍历数组来完成的。因此,总时间复杂度为O(n^2)。为了做得更好,您将需要一个附加的数据结构来在累加器中存储名称到索引的映射。然后您可以获得O(n)