Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

javascript - lodash - create a unique list based on multiple attributes

My collection looks like this.

  var list = [{id:'12345', sequence:null}, {id:'12346', sequence:null}, {id:'12347', sequence:null}, {id:'12348', sequence:1}, {id:'12348', sequence:2}, {id:'12349', sequence:1}, {id:'12349', sequence:1}];

I am trying to get a unique list so that object with same id AND sequence will only return one of the objects (we have 2 here- {id:'12349', sequence:1})

my code

  var uniqueList = _.uniq(list, function(obj) {
    return obj.id && obj.sequence;
  });

can we use lodash uniq like this? what is the approach to fix this issue?

like image 683
Sanath Avatar asked May 19 '16 07:05

Sanath


2 Answers

You can use uniqBy() to compute the criterion by which the list is generated wherein the iteratee callback returns the joined value of id and sequence of each item of the colection. The solution below works great when you only want to have specific properties to be the criterion of uniqueness especially when each object in your collection may not only have the id and sequence properties.

var result = _.uniqBy(list, v => [v.id, v.sequence].join());

var list = [{
  id: '12345',
  sequence: null
}, {
  id: '12346',
  sequence: null
}, {
  id: '12347',
  sequence: null
}, {
  id: '12348',
  sequence: 1
}, {
  id: '12348',
  sequence: 2
}, {
  id: '12349',
  sequence: 1
}, {
  id: '12349',
  sequence: 1
}, {
  id: '123490',
  sequence: 1,
  extra: 1
}, {
  id: '123490',
  sequence: 1,
  extra: 2
}];

var result = _(list)
  .uniqBy(v => [v.id, v.sequence].join())
  .value();

document.write('<pre>' + JSON.stringify(result, 0, 4) + '</pre>');
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.12.0/lodash.js"></script>

Alternatively, if you have properties that contains non-primitive values (objects or arrays) to be used as the criterion then you can still use the solution above but instead joining the array of values, you have to use JSON.stringify()

var result = _.uniqBy(list, v => JSON.stringify([v.id, v.sequence]));

var list = [{
  id: '12345',
  sequence: null
}, {
  id: '12346',
  sequence: null
}, {
  id: '12347',
  sequence: null
}, {
  id: '12348',
  sequence: 1
}, {
  id: '12348',
  sequence: 2
}, {
  id: '12349',
  sequence: 1
}, {
  id: '12349',
  sequence: 1
}, {
  id: '123490',
  sequence: 1,
  extra: 1
}, {
  id: '123490',
  sequence: 1,
  extra: 2
}];

var result = _.uniqBy(list, v => JSON.stringify([v.id, v.sequence]));

document.write('<pre>' + JSON.stringify(result, 0, 4) + '</pre>');
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.12.0/lodash.js"></script>

UPDATE:

For the lodash3 solution, for properties with primitive values, you can still use the pattern in the first solution using uniq().

var result = _.uniq(list, v => [v.id, v.sequence].join());

var list = [{
  id: '12345',
  sequence: null
}, {
  id: '12346',
  sequence: null
}, {
  id: '12347',
  sequence: null
}, {
  id: '12348',
  sequence: 1
}, {
  id: '12348',
  sequence: 2
}, {
  id: '12349',
  sequence: 1
}, {
  id: '12349',
  sequence: 1
}, {
  id: '123490',
  sequence: 1,
  extra: 1
}, {
  id: '123490',
  sequence: 1,
  extra: 2
}];

var result = _.uniq(list, v => [v.id, v.sequence].join());

document.write('<pre>' + JSON.stringify(result, 0, 4) + '</pre>');
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/3.10.1/lodash.js"></script>

And for the non-primitive properties, you can still use the 2nd example above with uniq()

var result = _.uniq(list, v => JSON.stringify([v.id, v.sequence]));

var list = [{
  id: '12345',
  sequence: null
}, {
  id: '12346',
  sequence: null
}, {
  id: '12347',
  sequence: null
}, {
  id: '12348',
  sequence: 1
}, {
  id: '12348',
  sequence: 2
}, {
  id: '12349',
  sequence: 1
}, {
  id: '12349',
  sequence: 1
}, {
  id: '123490',
  sequence: 1,
  extra: 1
}, {
  id: '123490',
  sequence: 1,
  extra: 2
}];

var result = _.uniq(list, v => JSON.stringify([v.id, v.sequence]));

document.write('<pre>' + JSON.stringify(result, 0, 4) + '</pre>');
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/3.10.1/lodash.js"></script>
like image 199
ryeballar Avatar answered Oct 08 '22 20:10

ryeballar


You may use uniqWith

This method is like _.uniq except that it accepts comparator which is invoked to compare elements of array. The comparator is invoked with two arguments: (arrVal, othVal).

and isEqual

Performs a deep comparison between two values to determine if they are equivalent.

_.uniqWith(list, _.isEqual);
like image 36
Nina Scholz Avatar answered Oct 08 '22 21:10

Nina Scholz