【问题标题】:Get unique values from array of objects using reduce function使用reduce函数从对象数组中获取唯一值
【发布时间】:2021-10-30 16:01:21
【问题描述】:

我有一个对象数组

const data = [{
    productId: 7000254,
    quantity: 1
}, {
    productId: 7000255,
    quantity: 1
}, {
    productId: 7000256,
    quantity: 1
}, {
    productId: 7000257,
    quantity: 1
}, {
    productId: 7000254,
    quantity: 1
}];

我需要使用 reduce 函数从中获取唯一值。

我用下面的代码做的

data.map((rp) => {
      if (products.map(({ productId }) => productId).indexOf(rp.productId) === -1) {
        products.push({ productId: parseInt(rp.productId), quantity: 1 })
      }
    })

但正如您所见,这是一个漫长的过程,因为我必须多次迭代数组。那么有没有办法使用reduce函数呢?

var unique = data.reduce((a, b ,c,d) => {
  if (a.map(({productId}) => productId).indexOf(b.productId) === -1) {
    return [a,b]
  }
})
console.log(unique)

预期输出

0: {productId: 7000254, quantity: 1}
1: {productId: 7000255, quantity: 1}
2: {productId: 7000256, quantity: 1}
3: {productId: 7000257, quantity: 1}

【问题讨论】:

    标签: javascript arrays unique reduce


    【解决方案1】:

    您可以使用filterSet 有效地实现此结果。

    const data = [{
        productId: 7000254,
        quantity: 1,
      },
      {
        productId: 7000255,
        quantity: 1,
      },
      {
        productId: 7000256,
        quantity: 1,
      },
      {
        productId: 7000257,
        quantity: 1,
      },
      {
        productId: 7000254,
        quantity: 1,
      },
    ];
    
    const set = new Set();
    const result = data.filter((o) => {
      if (set.has(o.productId)) return false;
      set.add(o.productId);
      return true;
    });
    
    console.log(result);
    /* This is not a part of answer. It is just to give the output fill height. So IGNORE IT */
    
    .as-console-wrapper {
      max-height: 100% !important;
      top: 0;
    }

    【讨论】:

    • 耶,我会选择这个而不是减少。它更易于阅读。
    • @Totati 与 reduce 相比,如果与 find 一起使用,时间复杂度也是 O(n)。
    • 您也可以将 Set 与 reduce 一起使用,但我仍然会选择 filter :D 您也可以使用 Map,但这意味着 2 次迭代,因为最后您需要将值映射回一个数组。
    • @malarres set.has 将在恒定时间内给出结果O(1)
    • 很高兴知道@HR01M8055,我从规范中得到它需要O(n)“一样多”,但我不知道它被实现为O(1) 来源:Set objects must be implemented using either hash tables or other mechanisms that, on average, provide access times that are sublinear on the number of elements in the collection. 262.ecma-international.org/6.0/#sec-set-objects
    【解决方案2】:

    Array.reduce 实现。

    逻辑

    • 遍历数组。
    • 在将其推送到累加器之前,请确认累加器中已经存在一个节点。
    • 如果节点存在,不要推送,否则推送到累加器。

    const data = [{
      productId: 7000254,
      quantity: 1
    }, {
      productId: 7000255,
      quantity: 1
    }, {
      productId: 7000256,
      quantity: 1
    }, {
      productId: 7000257,
      quantity: 1
    }, {
      productId: 7000254,
      quantity: 1
    }];
    const output = data.reduce((acc, curr) => {
      const matchingNode = acc.find(node => node.productId === curr.productId);
      if(!matchingNode) {
        acc.push(curr);
      }
      return acc;
    }, []);
    console.log(output)

    【讨论】:

    • find inside reduce 使其最差的时间复杂度为n * 2。您可以在此处使用Set 使其成为O(n)
    • @HR01M8055 问题是关于功能,而不是关于性能。
    • 我完全同意你的看法。但是,如果我们获得具有性能的功能,那就更好了。如果没有效率,该功能有什么用。你不觉得
    • @HR01M8055 同意。我们有很多性能优化。一个由你提供。我是否需要找到所有性能改进来修复它们?
    【解决方案3】:

    无需多次迭代的最佳方法是使用 reduce 类似的东西

    const output = data.reduce((pv, cv) => {
        if (pv.array.indexOf(cv.productId) === -1) {
        return { array: [...pv.array, cv.productId], output: [...pv.output, cv] }
      }
      return pv;
    }, { array: [], output: [] })
    
    console.log({ output })
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2020-11-13
      • 2019-10-20
      • 1970-01-01
      • 2019-11-14
      • 1970-01-01
      • 2019-01-03
      • 1970-01-01
      相关资源
      最近更新 更多