2

I have array of objects, objects have properties say "a", "b" and "c". Now I need to filter out objects which has unique values of "a & b". However c plays role on which objects to keep and which ones to reject.

If I do uniqBy on properties a and b, I will be blindly rejecting other objects. It will keep the first object it encounters in the array and reject all other duplicates.

Let me know if you need more clarification on the question.

This is how I found the uniq objects based on two properties. var uniqArray= _.uniqBy(obj, function(elem) { return [elem.a, elem.b].join(); })

lodash uniq - choose which duplicate object to keep in array of objects

Do we have better solution?

Here is an example of input and expected output Input: var arrayOfObj = [{a:1, b:1, c:2}, {a:1,b:1,c:1}, {a:2, b:2,c:2}]; Output: arrayOfObj = [{a:1,b:1,c:1}, {a:2, b:2,c:2}]; there should not be any duplicate a1,b1 combination

Community
  • 1
  • 1

2 Answers2

2

According to Lodash documentation, the order of result values is determined by the order they occur in the array. Therefore you need to order the array using the 'c' property in order to get the expected result.

To do so, you can use _.sortBy. It orders a collection in asc order based on a property or an iteratee. I think your problem could be solved using a property directly though you could use a function to provide a more accurate comparator if needed.

After that, you just perform the uniqBy action and retrieve the result:

var res = _(arrayOfObj)
  .orderBy('c')
  .uniqBy('a', 'b')
  .value();

console.log(res);

Here's the fiddle.

As I read in the comments, your 'c' property is a timestamp. If you want to order from latest to newest, you can pass an iteratee to sort by in order to reverse the natural order by 'c':

var res = _(arrayOfObj)
  .orderBy(function(obj) {
    return -(+obj.c);
  })
  .uniqBy('a', 'b')
  .value();

console.log(res);

You can check it out in this update of the previous fiddle. Hope it helps.

acontell
  • 6,792
  • 1
  • 19
  • 32
0

Would help to know what the actual data is and what you want to achieve with it. Here's an idea: group your objects based on a and b, then from each grouping, select one item based on c.

var arrayOfObj = [
{a:1, b:1, c:2}, 
{a:1, b:1, c:1}, 
{a:2, b:2, c:2}
];

var result = _.chain(arrayOfObj)
    .groupBy(function (obj) {
        return obj.a.toString() + obj.b.toString();
    })
    .map(function (objects) {

        //replace with code to select the right item based on c
        return _.head(objects);

    }).value();
Piittis
  • 318
  • 2
  • 7