Javascript - 计算对象数组中的重复项并将计数存储为新对象

Posted

技术标签:

【中文标题】Javascript - 计算对象数组中的重复项并将计数存储为新对象【英文标题】:Javascript - Counting duplicates in object array and storing the count as a new object 【发布时间】:2017-12-28 17:44:54 【问题描述】:

我有一组作为产品的 javascript 对象。这些产品以购物车的形式显示在列表中。

我想根据_.id 值计算数组中重复产品的数量,并从数组中删除这些对象,并用更新的版本和一个名为count 的新键替换它们,其值为总计此对象出现的次数。

到目前为止,我已经尝试了多种方法,并且在 google 上进行了搜索,但没有发现可以正确完成这项工作。

我将使用的数组类型示例如下:

[

      _id: "5971df93bfef201237985c4d", 
       slug: "5971df93bfef201237985c4d", 
       taxPercentage: 23, 
       totalCost: 9.99, 
       currency: "EUR", 
    ,

]

所以我希望我的最终结果是这样的 - 它删除重复值并用相同的对象替换它,但添加一个名为 count 的新键,其值是对象最初的次数在数组中:

[

      _id: "5971df93bfef201237985c4d", 
       slug: "5971df93bfef201237985c4d", 
       taxPercentage: 23, 
       totalCost: 9.99, 
       currency: "EUR", 
       count: 2, // whatever the count is
    ,

]

到目前为止,我都在使用这种方法:

var count = [];

if (cart.cart.products != undefined) 
    let namestUi = 
        renderNames(names)
            return Array.from(
                names.reduce( (counters, object) =>
                        counters.set(object._id, (counters.get(object._id) || 0) + 1),
                    new Map() ),
                ([object, count]) => 
                    var filterObj = names.filter(function(e) 
                        return e._id == object;
                    );

                    return (filterObj, count)
                
            );
        
    ;

    count = namestUi.renderNames(cart.cart.products);
    console.log(count)

但它返回如下值:

filterObj: Array // the array of the duplicates, count: 2
filterObj: Array, count: 1

并且由于我使用带有列表视图的 React-Native,因此这样的事情将无法正常工作。

它只需要以以前的方式(一个数组)存储项目,但有一个名为 count 的新子项。

欢迎任何帮助!

【问题讨论】:

您有一个对象数组,其中相同 id 的对象多次出现。现在您想创建一个数组,它将相同的对象组合成一个并添加一个计数属性(指示相同对象出现了多少次)。这是正确的吗?? 是的,差不多了 【参考方案1】:

我会坚持reduce,使用Map 并传播其values 以获得最终结果:

const names = [  _id: 1 ,  _id: 1,  _id: 2,  _id: 1];

const result = [...names.reduce( (mp, o) => 
    if (!mp.has(o._id)) mp.set(o._id,  ...o, count: 0 );
    mp.get(o._id).count++;
    return mp;
, new Map).values()];

console.log(result);

或者您可以先在映射中创建计数为零的所有键(使用 Map 构造函数),然后再次迭代数据以更新计数器。这种任务拆分使得代码比reduce更简洁:

const names = [  _id: 1 ,  _id: 1,  _id: 2,  _id: 1];

const mp = new Map(names.map(o => [o._id, ...o, count: 0 ]));
for (const _id of names) mp.get(_id).count++;
const result = Array.from(mp.values());

console.log(result);

当您拥有多个密钥时,一个想法是加入JSON.stringify([ ])

const names = [cat: 1, sub: 1, cat: 1, sub: 2, cat: 2, sub: 1, cat: 1, sub: 1];

const result = [...names.reduce( (mp, o) => 
    const key = JSON.stringify([o.cat, o.sub]);
    if (!mp.has(key)) mp.set(key,  ...o, count: 0 );
    mp.get(key).count++;
    return mp;
, new Map).values()];

console.log(result);

【讨论】:

这个结果也很好,更简洁更好的语法【参考方案2】:

最简单的可能是地图:

var map=new Map();

names.forEach(function(el)
 if(map.has(el["_id"]))
  map.get(el["_id"]).count++;
 else
  map.set(el["_id"],Object.assign(el,count:1));
 
);  

然后重新创建一个数组:

names=[...map.values()];

或者以旧的哈希/数组方式:

var hash=,result=[];

names.forEach(function(name)
  var id=name["_id"];
  if(hash[id])
     hash[id].count++;
  else
     result.push(hash[id]=
        count:1,
        ...name
     );
  
);

console.log(result);

【讨论】:

使用Object.assign(el,count:1) 修改原始对象。您应该执行相反的操作:Object.assign(count:1, el),或者,处理并覆盖现有的 count 属性:Object.assign(, el, count:1) @trincot 是的,提供了两种解决方案,我认为如果他关心性能或原始不变,我认为 OP 可以选择一个 mixin。【参考方案3】:

您可以使用array.reduce 方法将原始数组转换为具有所需结构的新数组。 我们可以只检查 id 是否存在于数组中,并相应地使用具有 count 属性的新对象更新数组。

let arr = [
  id: 1
, 
  id: 1
, 
  id: 1
, 
  id: 2
, 
  id: 2
];

let new_arr = arr.reduce((ar, obj) => 
  let bool = false;
  if (!ar) 
    ar = [];
  
  ar.forEach((a) => 
    if (a.id === obj.id) 
      a.count++;
      bool = true;
    
  );
  if (!bool) 
    obj.count = 1;
    ar.push(obj);
  
  return ar;
, []);

console.log(new_arr);

【讨论】:

以上是关于Javascript - 计算对象数组中的重复项并将计数存储为新对象的主要内容,如果未能解决你的问题,请参考以下文章

Javascript - 计算对象数组中的重复项并将计数存储为新对象

删除“case when”中的重复项并计算步骤之间的平均值

将键添加到 json 文件,删除重复项并在 javascript 中写入 json 文件

C# Unity如何只选择数组中的一项并取消选择其他项

JavaScript ES6 - 计算对象数组的重复项

javascript Javascript:计算数组中的重复项