开发者问题收集

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

2017-07-22
10976

我有一个 javascript 对象数组,它们是产品。这些产品以购物车的形式显示在列表中。

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

到目前为止,我已经尝试了多种方法,并在谷歌上搜索过,但没有找到可以正确完成工作的方法。

我将使用的数组类型的一个示例是这样的:

[

    {  _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 的新子项。

欢迎任何帮助!

3个回答

我会坚持使用 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);
trincot
2017-07-22

最简单的可能是一张地图:

2222352337

,然后重新创建一个数组:

753639766

哈希/数组方式:

809057340
Jonas Wilms
2017-07-22

您可以使用 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);
Anurag Singh Bisht
2017-07-22