【问题标题】:Get list of duplicate objects in an array of objects获取对象数组中重复对象的列表
【发布时间】:2019-04-12 05:08:30
【问题描述】:

我正在尝试在对象数组中获取重复的对象。假设对象如下所示。

values = [
  { id: 10, name: 'someName1' },
  { id: 10, name: 'someName2' },
  { id: 11, name: 'someName3' },
  { id: 12, name: 'someName4' }
];

重复的对象应该返回如下:

duplicate = [
  { id: 10, name: 'someName1' },
  { id: 10, name: 'someName2' }
];

【问题讨论】:

  • 你的问题是什么?
  • 试试如何?您还没有向我们展示任何试图解决此问题的代码。数组重复项的网络搜索应该为您提供了一个良好的起点

标签: javascript arrays typescript ecmascript-6 lodash


【解决方案1】:

您可以使用Array#reduce 根据id 键创建计数器查找表,然后使用Array#filter 删除在查找表中仅出现一次的任何项目。时间复杂度为 O(n)。

const values = [{id: 10, name: 'someName1'}, {id: 10, name: 'someName2'}, {id: 11, name:'someName3'}, {id: 12, name: 'someName4'}];

const lookup = values.reduce((a, e) => {
  a[e.id] = ++a[e.id] || 0;
  return a;
}, {});

console.log(values.filter(e => lookup[e.id]));

【讨论】:

  • 您能解释一下您的代码吗?我很困惑。您的代码中没有任何相等性是如何工作的?为什么a 在每次迭代中都显示相同的对象?我需要详细分析你的代码。
  • 如果您还没有,我建议您查看 reducefilter 的文档。我使用reduce 构建每个对象的id 到其occurrences - 1 计数的对象映射。 a 是由reduce 从一个回调传递到下一个回调的累加器对象。 filter 使用 lookup[e.id] 的真实性来确定元素是否唯一。如果查找条目为 0(错误),则它只被看到一次,filter 从结果集中忽略它,否则它会被保留。
  • 其实我知道reduce(不是专家但知道)和filter。并且知道它们是如何工作的。但是很难理解你的代码。但是有了你的解释,一切都变得容易了一点: ) 谢谢。
  • 这是非常聪明的代码,我认为你的解释不公平@ggorlen!为了准确解释reduce内部发生的事情,这里是:数组中的每个项目都由箭头函数处理,并且在查找中创建一个属性(新项目),或者增加计数器(我们点击重复项)。其工作原理如下: a[e.id] = ++a[e.id] ||如果属性已经存在,0 只会使用 ++ 增加属性。如果不是,那么它将通过 OR (||) 并创建一个值为 0 的属性。
  • @ggorlen 我们可以比较多个字段 ID 和名称吗?
【解决方案2】:

假设你有:

arr = [
    { id:10, name: 'someName1' },
    { id:10, name: 'someName2' },
    { id:11, name: 'someName3' },
    { id:12, name: 'someName4' }
]

所以,要获得独特的物品:

unique = arr
     .map(e => e['id'])
     .map((e, i, final) => final.indexOf(e) === i && i)
     .filter(obj=> arr[obj])
     .map(e => arr[e]);

然后,结果将是

unique = [
     { id:10, name: 'someName1' },
     { id:11, name: 'someName3' },
     { id:12, name: 'someName4' }
]

而且,要获得重复的 id:

duplicateIds = arr
     .map(e => e['id'])
     .map((e, i, final) => final.indexOf(e) !== i && i)
     .filter(obj=> arr[obj])
     .map(e => arr[e]["id"])

ID 列表将是

duplicateIds = [10]

因此,要获取重复对象:

duplicate = arr.filter(obj=> dublicateIds.includes(obj.id));

现在你有了它:

duplicate = [
    { id:10, name: 'someName1' },
    { id:10, name: 'someName2' }
]

谢谢https://reactgo.com/removeduplicateobjects/

【讨论】:

  • 我们如何找出多个属性的重复项?
  • 我不是你的意思@Vivek,如果你有输入和预期输出的例子,那么我可以帮忙!
  • 感谢您回来,我在您的回答中使用了完全相同的示例。在您的示例中,我们根据 ID 查找重复项。如果我们必须找出重复的 ID 和 name 属性,需要进行哪些更改?任何帮助将不胜感激
  • 你可以通过将 ".map(e => e['id'])" 替换为 ".map(e => e['id']+'_'+e ['名称'])"
  • 我们怎么称呼它?
【解决方案3】:

您尚未澄清两个具有不同 ID 但“名称”相同的对象是否算作重复。我会假设那些不算作重复;换句话说,只有具有相同 id 的对象才会被视为重复对象。

let ids = {};
let dups = [];

values.forEach((val)=> {
  if (ids[val.id]) {
    // we have already found this same id
    dups.push(val)
  } else {
    ids[val.id] = true;
  }
})
return dups;

【讨论】:

    【解决方案4】:

    使用 lodash,您可以使用 filtercountBy 解决这个问题,因为复杂性是 O(n)

    const data = [{ id: 10,name: 'someName1' }, { id: 10,name: 'someName2' }, { id: 11,name: 'someName3' }, { id: 12,name: 'someName4' } ]
    
    const counts = _.countBy(data, 'id')
    console.log(_.filter(data, x => counts[x.id] > 1))
    <script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.10/lodash.min.js"></script>

    你可以像这样对 ES6 做同样的事情:

    const data = [{ id: 10,name: 'someName1' }, { id: 10,name: 'someName2' }, { id: 11,name: 'someName3' }, { id: 12,name: 'someName4' } ]
    
    const countBy = (d, id) => d.reduce((r,{id},i,a) => (r[id] = a.filter(x => x.id == id).length, r),{})
    const counts = countBy(data, 'id')
    console.log(data.filter(x => [x.id] > 1))

    【讨论】:

      【解决方案5】:

      您可以使用数组来存储唯一元素,并对值使用过滤器以仅返回重复项。

      const unique = []
      
      const duplicates = values.filter(o => {
      
         if(unique.find(i => i.id === o.id && i.name === o.name)) {
           return true
         }
      
         unique.push(o)
         return false;
      })
      

      【讨论】:

        【解决方案6】:

        使用 lodash,您可以使用 _.groupBy() 按元素的 id 对元素进行分组。比_.filter() 出组的成员少于两个,而_.flatten() 结果:

        const values = [{id: 10, name: 'someName1'}, {id: 10, name: 'someName2'}, {id: 11, name:'someName3'}, {id: 12, name: 'someName4'}];
        
        const result = _.flow([
          arr => _.groupBy(arr, 'id'), // group elements by id
          g => _.filter(g, o => o.length > 1), // remove groups that have less than two members
          _.flatten // flatten the results to a single array
        ])(values);
        
        console.log(result);
        <script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.11/lodash.min.js"></script>

        【讨论】:

          【解决方案7】:

          基于@ggorlen 解决方案的替代方案,使用 new Map() 作为累加器(以获得更好的性能)并且没有一元运算符 ++ (not advised by default in projects with ESLint)。

          const values = [{ id: 10, name: "someName1" }, { id: 10, name: "someName2" }, { id: 11, name: "someName3" }, { id: 12, name: "someName4" },];
          
          const lookup = values.reduce((a, e) => {
            a.set(e.id, (a.get(e.id) ?? 0) + 1);
            return a;
          }, new Map());
          
          console.log(values.filter(e => lookup.get(e.id) > 1));

          【讨论】:

            【解决方案8】:

            试试这个

            function checkDuplicateInObject(propertyName, inputArray) {
              var seenDuplicate = false,
              testObject = {};
            
              inputArray.map(function(item) {
              var itemPropertyName = item[propertyName];    
              if (itemPropertyName in testObject) {
              testObject[itemPropertyName].duplicate = true;
              item.duplicate = true;
              seenDuplicate = true;
             }
             else {
               testObject[itemPropertyName] = item;
               delete item.duplicate;
             }
            });
            
             return seenDuplicate;
            }
            

            引用自:http://www.competa.com/blog/lets-find-duplicate-property-values-in-an-array-of-objects-in-javascript/

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 2020-11-24
              • 1970-01-01
              • 2023-03-18
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 2021-11-08
              • 2021-09-14
              相关资源
              最近更新 更多