【问题标题】:Get objects containing same id in array of objects into new array将对象数组中包含相同 id 的对象放入新数组中
【发布时间】:2021-05-30 01:25:40
【问题描述】:

我想将所有具有相同 id 的对象放入一个新数组中。 在下面的数据中,id: 1 的第一个对象在第 3 和第 5 位置重复,所以我需要将第 1、第 3 和第 5 位置对象存储到新数组中。如果在数据中重复更多 id,也是一样

数据:

const data = [
  { id: 1, file: 'test1.xlsx' },
  { id: 3, file: 'test1.xlsx' },
  { id: 1, file: 'test2.xlsx' },
  { id: 5, file: 'test2.xlsx' },
  { id: 1, file: 'test3.xlsx' },
  { id: 7, file: 'test3.xlsx' },
  { id: 8, file: 'test4.xlsx' },
  { id: 9, file: 'test4.xlsx' },
  { id: 9, file: 'test5.xlsx' },
  { id: 10, file: 'test5.xlsx' },
  { id: 9, file: 'test6.xlsx' },
]

我的代码:

// arr = data
// headerKey = 'id'
const getDuplicates = (arr, headerKey) => {
  return arr
    .map((el, i) => {
      return arr.find((element, index) => {
        if (i !== index && element[headerKey] === el[headerKey]) {
          return el
        }
      })
    })
    .filter((x) => x)
}

我的输出不正确

[
  { id: 1, file: 'test2.xlsx' },
  { id: 1, file: 'test1.xlsx' },
  { id: 1, file: 'test1.xlsx' },
  { id: 9, file: 'test5.xlsx' },
  { id: 9, file: 'test4.xlsx' },
  { id: 9, file: 'test4.xlsx' }
]

预期输出

[
  { id: 1, file: 'test1.xlsx' },
  { id: 1, file: 'test2.xlsx' },
  { id: 1, file: 'test3.xlsx' },
  { id: 9, file: 'test4.xlsx' },
  { id: 9, file: 'test5.xlsx' },
  { id: 9, file: 'test6.xlsx' }
]

在不正确的输出部分中,{ id: 1, file: 'test1.xlsx' } 的对象被重复了 2 次,这不应该是这种情况,其他重复条目也是如此。

我想,我能够弄清楚我当前的问题,输出不正确的原因可能是因为find()方法只返回第一个元素。

我在网上搜索了解决方案,很多人建议使用reduce,或filter方法,但我不知道如何实现。

【问题讨论】:

    标签: javascript arrays algorithm duplicates


    【解决方案1】:

    我们可以通过使用Object.valuesArray.reduce 来实现预期的输出,最后检查累加数组的长度以获取重复的id 和下面的相应文件。

    const data = [{id:1,file:'test1.xlsx'},{id:3,file:'test1.xlsx'},{id:1,file:'test2.xlsx'},{id:5,file:'test2.xlsx'},{id:1,file:'test3.xlsx'},{id:7,file:'test3.xlsx'},{id:8,file:'test4.xlsx'},{id:9,file:'test4.xlsx'},{id:9,file:'test5.xlsx'},{id:10,file:'test5.xlsx'},{id:9,file:'test6.xlsx'}];
    
    const findDuplicates = (data) => {
      const output = [];
      Object.values(data.reduce((res, obj) => {
        let key = obj.id;
        res[key] = [...(res[key] || []), {...obj}]
        return res;
      }, {})).forEach(arr => {
        if(arr.length > 1) {
          output.push(...arr);
        }
      });
      return output;
    }
    
    console.log(findDuplicates(data));
    .as-console-wrapper {
      max-height: 100% !important;
    }

    【讨论】:

      【解决方案2】:

      为了降低计算复杂度,不要在 .map 中使用 .find - 那是 O(n ^ 2)。我会计算给定id 在对象(或地图)上出现的次数,然后最后,按其中至少包含 2 个值的集合过滤值:

      const data = [
        { id: 1, file: 'test1.xlsx' },
        { id: 3, file: 'test1.xlsx' },
        { id: 1, file: 'test2.xlsx' },
        { id: 5, file: 'test2.xlsx' },
        { id: 1, file: 'test3.xlsx' },
        { id: 7, file: 'test3.xlsx' },
        { id: 8, file: 'test4.xlsx' },
        { id: 9, file: 'test4.xlsx' },
        { id: 9, file: 'test5.xlsx' },
        { id: 10, file: 'test5.xlsx' },
        { id: 9, file: 'test6.xlsx' },
      ]
      
      // arr = data
      // headerKey = 'id'
      const getDuplicates = (arr, headerKey) => {
        const objsByHeader = {};
        for (const obj of arr) {
          objsByHeader[obj[headerKey]] ??= [];
          objsByHeader[obj[headerKey]].push(obj);
        }
        return Object.values(objsByHeader)
          .filter(subarr => subarr.length >= 2)
          .flat();
      }
      console.log(getDuplicates(data, 'id'));

      【讨论】:

      • index.js:51 objsByHeader[obj[headerKey]] ??= [] ^ SyntaxError: Unexpected token '=' 我收到了这个错误,我想指出我是使用nodejs,
      • ??=Logical nullish assignment,从 nodejs v15.0.0 开始兼容。
      • @PawanKanhere 如果你不能使用??=,那么你可以使用if (!objsByHeader[obj[headerKey]]) objsByHeader[obj[headerKey]] = []
      猜你喜欢
      • 2020-10-03
      • 2016-01-30
      • 2021-09-10
      • 1970-01-01
      • 1970-01-01
      • 2023-03-29
      • 1970-01-01
      • 2021-07-12
      • 1970-01-01
      相关资源
      最近更新 更多