Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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'
  }
];
like image 341
Zze Avatar asked Apr 06 '17 04:04

Zze


People also ask

How can I get unique objects from an array of objects?

One way to get distinct values from an array of JavaScript objects is to use the array's map method to get an array with the values of a property in each object. Then we can remove the duplicate values with the Set constructor. And then we can convert the set back to an array with the spread operator.

How do you filter one property from an array of objects?

One can use filter() function in JavaScript to filter the object array based on attributes. The filter() function will return a new array containing all the array elements that pass the given condition. If no elements pass the condition it returns an empty array.

Can we apply filter method to an object?

JavaScript's Objects are not iterable like arrays or strings, so we can't make use of the filter() method directly on an Object . filter() allows us to iterate through an array and returns only the items of that array that fit certain criteria, into a new array.


1 Answers

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);
});
like image 92
nnnnnn Avatar answered Oct 14 '22 06:10

nnnnnn