简体   繁体   中英

Filter array to unique objects by object.property

What I am trying to achieve is filtering of the objects array so that I get an array of objects with unique actors.

So this is what I currently have:

 var objects = [{ actor: { account: null, degraded: false, mbox: null, mbox_sha1sum: "843c56da78f9eb888274d2d4e12ab1d748ec46234", name: "name", openid: null }, capture: 'value' }, { actor: { account: null, degraded: false, mbox: null, mbox_sha1sum: "843c56da78f9eb888274d2d4e12ab1d748ec12345", name: "name2", openid: null }, capture: 'value2' }, { actor: { account: null, degraded: false, mbox: null, mbox_sha1sum: "843c56da78f9eb888274d2d4e12ab1d748ec46234", name: "name", openid: null }, capture: 'value3' } ]; objects.filter((value, index, self) => { return self.indexOf(value) === index; }).map(ele => { console.log(ele.capture); });

The desired outcome is an array which does not consist of the last array element as this actor property matches the first array element.

But as you can see, at the moment it does not filter any of the array elements.

At first I thought that return self.indexOf(value.value) === index; would solve this issue, however this returns an empty array.

The expected result is:

[{
    actor: {
      account: null,
      degraded: false,
      mbox: null,
      mbox_sha1sum: "843c56da78f9eb888274d2d4e12ab1d748ec46234",
      name: "name",
      openid: null
    },
    capture: 'value'
  },
  {
    actor: {
      account: null,
      degraded: false,
      mbox: null,
      mbox_sha1sum: "843c56da78f9eb888274d2d4e12ab1d748ec12345",
      name: "name2",
      openid: null
    },
    capture: 'value2'
  }
];

The objects in your array are all different objects, even if some happen to have properties with the same values. The .indexOf() function is comparing references, not property values.

Also, in practice, none of the three objects have identical properties because they all have a different .capture value.

Use .findIndex() instead of .indexOf() , so that you can compare the properties to find matching objects:

objects.filter((value, index, self) => {
  return self.findIndex(v => v.actor.name === value.actor.name) === index;
})

Here I'm just using the .actor.name property, but of course you could compare additional properties if needed.

(Note that .findIndex() is an ES6 function, but I assume that's fine given that your code is already using arrow functions. Or you can polyfill it .)

 var objects = [{ actor: { account: null, degraded: false, mbox: null, mbox_sha1sum: "843c56da78f9eb888274d2d4e12ab1d748ec46234", name: "name", openid: null }, capture: 'value' }, { actor: { account: null, degraded: false, mbox: null, mbox_sha1sum: "843c56da78f9eb888274d2d4e12ab1d748ec12345", name: "name2", openid: null }, capture: 'value2' }, { actor: { account: null, degraded: false, mbox: null, mbox_sha1sum: "843c56da78f9eb888274d2d4e12ab1d748ec46234", name: "name", openid: null }, capture: 'value3' } ]; objects.filter((value, index, self) => { return self.findIndex(v => v.actor.name === value.actor.name) === index; }).map(ele => { console.log(ele.capture); });

If you can use Object Literal to filter the unique element as well.

 var objects = [{ actor: { account: null, degraded: false, mbox: null, mbox_sha1sum: "843c56da78f9eb888274d2d4e12ab1d748ec46234", name: "name", openid: null }, capture: 'value' }, { actor: { account: null, degraded: false, mbox: null, mbox_sha1sum: "843c56da78f9eb888274d2d4e12ab1d748ec46234", name: "name", openid: null }, capture: 'value3' } ]; const uniqueObjMap = {}; for (const object of objects) { uniqueObjMap[object.actor.name] = object; } const uniqueObjects = Object.values(uniqueObjMap); console.log(uniqueObjects)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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