简体   繁体   English

从对象数组中提取唯一值,其中值是 JavaScript 中的嵌套对象

[英]Extracting unique values from an array of objects where value is a nested object in JavaScript

Let's say I've got the following array of objects in JavaScript:假设我在 JavaScript 中有以下对象数组:

const requests = [
  {
    id: 1,
    person: {
      id: 1
    }
  },
  {
    id: 2,
    person: {
      id: 1
    }
  },
  {
    id: 3,
    person: {
      id: 2
    }
  },
  {
    id: 4,
    person: {
      id: 3
    }
  },
  {
    id: 5,
    person: {
      id: 2
    }
  }
]

And what I've written below will go over each item in the array, and then create a new array containing just the person object.我在下面写的内容将遍历数组中的每个项目,然后创建一个仅包含person对象的新数组。

const requestsPeopleIds = []
for (const request of requests) {
  requestsPeopleIds.push(request.person.id)
}

I then take that new array and create another new array using Set to remove the duplicate id s:然后我使用该新数组并使用Set创建另一个新数组以删除重复的id

const uniquePeopleIds = Array.from(new Set(requestsPeopleIds))

The final result is as I'd expect:最终结果如我所料:

console.log(uniquePeopleIds) // [1, 2, 3]

where these are the unique id s of the people who made a request.其中这些是提出请求的人的唯一id So out of the 5 requests, these were made by 3 people.所以在5请求中,这些是由3个人提出的。

There must be a more efficient way of doing this, so I'm reaching out to you stack overflow JS gurus.必须有一种更有效的方法来做到这一点,所以我正在与stack overflow JS 大师联系。

Thanks in advance.提前致谢。

I think you got the basics.我想你已经掌握了基础知识。 Here's a way to tighten the code:这是一种收紧代码的方法:

var ids = new Set;
requests.forEach(i => ids.add(i.person.id));

You could also do this with map method and spread syntax ... .你也可以用map方法和传播语法来做到这一点...

 const requests = [{"id":1,"person":{"id":1}},{"id":2,"person":{"id":1}},{"id":3,"person":{"id":2}},{"id":4,"person":{"id":3}},{"id":5,"person":{"id":2}}] const result = [...new Set(requests.map(({ person: { id }}) => id))] console.log(result)

You can do it by making an object by the person's id as a key and get the keys of the object.您可以通过以该人的 id 为键创建一个对象并获取该对象的键来实现。

 const requests = [{"id":1,"person":{"id":1}},{"id":2,"person":{"id":1}},{"id":3,"person":{"id":2}},{"id":4,"person":{"id":3}},{"id":5,"person":{"id":2}}] // Take an empty object const uniques = {}; // Iterate through the requests array and make person's id as a // key of the object and put any value at this index (here I put 1). requests.forEach(request => (uniques[request.person.id] = 1)); // Finally get the keys of the unique object. console.log(Object.keys(uniques));

I've done some research and have inferred some interesting facts:我做了一些研究,并推断出一些有趣的事实:

  1. It looks like when we have very various data and larger array, then Set collection shows not best results.看起来当我们有各种各样的数据和更大的数组时, Set集合显示的结果不是最好的。 Set is very optimized collection, however, in my view, it should always check whether element is already added into Set . Set是非常优化的集合,但是,在我看来,它应该始终检查元素是否已经添加到Set And this checking will take O(n) complexity.这个检查需要O(n)复杂度。 But we can use simple JavaScript object .但是我们可以使用简单的 JavaScript object Checking whether object contains key is O(1).检查object是否包含键是 O(1)。 So object will have huge advantage over Set .因此object将比Set具有巨大的优势。

  2. foreach arrow function is very convenient, however, simple for loop is faster. foreach箭头函数非常方便,但是简单的for循环更快。

  3. Adding console.log makes Set the most fastest solution, however, without console.log , the most fastest solution is combination of for loop and object .添加console.log使Set成为最快的解决方案,但是,如果没有console.log ,最快的解决方案是for循环和object组合。

So the most performant code without console.log() looks like this:因此,没有console.log()的最console.log()代码如下所示:

const hashMap = {};
const uniques = [];
for (let index = 0; index < requests.length; index++) {  
  if (!hashMap.hasOwnProperty(requests[index].person.id)){
      hashMap[requests[index].person.id] = 1;
      uniques.push(requests[index].person.id);
  }
}

However, the most performant code with console.log() looks like this(I cannot understand the reason why it happens. It would be really great to know why it happens):但是, console.log()性能最好的代码如下所示(我无法理解它发生的原因。知道它为什么会发生真的很棒):

var ids = new Set;
requests.forEach(i => ids.add(i.person.id));
console.log(ids)

Tests:测试:

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM