Imo Imo - 5 months ago 13
AngularJS Question

Find a JSON object with property matched more than once

I need to find every element in the json array with same name property for example here Alaska is two times then I need to compare the lastupdate of both of the objects and choose the one with latest update time. Adopting from an answer in stackoverflow (sorry I lost the link) I can remove the object with same name property but how can I keep the one with latest update time?

[{
"name": "Alaska",
"Republican_fre": 3,
"Democrats_fre": 0,
"winner": "R",
"iso_2": "AK",
"electoral_vote": 3,
"totalComponents": 3,
"date": "29.06.2016",
"lastupdate": "1467233426"
}, {
"name": "Alabama",
"Republican_fre": 3,
"Democrats_fre": 0,
"winner": "R",
"iso_2": "AL",
"electoral_vote": 9,
"totalComponents": 3,
"date": "29.06.2016",
"lastupdate": "1467233426"
}, {
"name": "Arkansas",
"Republican_fre": 2,
"Democrats_fre": 0,
"winner": "R",
"iso_2": "AR",
"electoral_vote": 6,
"totalComponents": 2,
"date": "29.06.2016",
"lastupdate": "1467233426"
},
{
"name": "Alaska",
"Republican_fre": 5,
"Democrats_fre": 0,
"winner": "R",
"iso_2": "AK",
"electoral_vote": 3,
"totalComponents": 5,
"date": "29.06.2016",
"lastupdate": "1467282133"
}]


code:

function arrUnique(arr) {
var cleaned = [];
data.forEach(function(itm) {
var unique = true;
cleaned.forEach(function(itm2) {
var minValue = Math.min(itm.lastupdate, itm2.lastupdate)
if (_.isEqual(itm.name, itm2.name)){
unique = false;
}
});
if (unique) cleaned.push(itm);
});
return cleaned;
}

var uniqueStandards = arrUnique(data);


jsfiddle:

Expected Output
The expected output is that it keeps the one of the Alsaka objects with lastest 'lastupdate' value. So it first checks for the objects with same name property then compares the lastupdate value and keeps the one with latest value

Answer

You can use underscore's sortBy() to sort items in the collection by their lastupdate key, reverse() to have all the items ordered by lastupdate in descending order, and then use uniq() to only preserve unique name items.

var uniqueStandards = _.uniq(_.sortBy(data, 'lastupdate').reverse(), 'name');

var data = [{
  "name": "Alaska",
  "Republican_fre": 3,
  "Democrats_fre": 0,
  "winner": "R",
  "iso_2": "AK",
  "electoral_vote": 3,
  "totalComponents": 3,
  "date": "29.06.2016",
  "lastupdate": "1467233426"
}, {
  "name": "Alabama",
  "Republican_fre": 3,
  "Democrats_fre": 0,
  "winner": "R",
  "iso_2": "AL",
  "electoral_vote": 9,
  "totalComponents": 3,
  "date": "29.06.2016",
  "lastupdate": "1467233426"
}, {
  "name": "Arkansas",
  "Republican_fre": 2,
  "Democrats_fre": 0,
  "winner": "R",
  "iso_2": "AR",
  "electoral_vote": 6,
  "totalComponents": 2,
  "date": "29.06.2016",
  "lastupdate": "1467233426"
}, {
  "name": "Alaska",
  "Republican_fre": 5,
  "Democrats_fre": 0,
  "winner": "R",
  "iso_2": "AK",
  "electoral_vote": 3,
  "totalComponents": 5,
  "date": "29.06.2016",
  "lastupdate": "1467282133"
}];

var uniqueStandards = _.uniq(_.sortBy(data, 'lastupdate').reverse(), 'name');

document.body.innerHTML = '<pre>' + JSON.stringify(uniqueStandards, 0, 4) + '</pre>';
<script src="https://cdnjs.cloudflare.com/ajax/libs/underscore.js/1.8.3/underscore-min.js"></script>


A vanilla JS solution would be:

var uniqueStandards = data
.slice() // this makes sure that we're not mutating the original array
.sort(function(x, y) { return y.lastupdate - x.lastupdate; }) // sort in descending order
.filter(function(x) {  // this ensure items with unique names
  return (this[x.name]? false: (this[x.name] = true));
}, {});

var data = [{
  "name": "Alaska",
  "Republican_fre": 3,
  "Democrats_fre": 0,
  "winner": "R",
  "iso_2": "AK",
  "electoral_vote": 3,
  "totalComponents": 3,
  "date": "29.06.2016",
  "lastupdate": "1467233426"
}, {
  "name": "Alabama",
  "Republican_fre": 3,
  "Democrats_fre": 0,
  "winner": "R",
  "iso_2": "AL",
  "electoral_vote": 9,
  "totalComponents": 3,
  "date": "29.06.2016",
  "lastupdate": "1467233426"
}, {
  "name": "Arkansas",
  "Republican_fre": 2,
  "Democrats_fre": 0,
  "winner": "R",
  "iso_2": "AR",
  "electoral_vote": 6,
  "totalComponents": 2,
  "date": "29.06.2016",
  "lastupdate": "1467233426"
}, {
  "name": "Alaska",
  "Republican_fre": 5,
  "Democrats_fre": 0,
  "winner": "R",
  "iso_2": "AK",
  "electoral_vote": 3,
  "totalComponents": 5,
  "date": "29.06.2016",
  "lastupdate": "1467282133"
}];

var uniqueStandards = data
.slice() // this makes sure that we're not mutating the original array
.sort(function(x, y) { return y.lastupdate - x.lastupdate; }) // sort in descending order
.filter(function(x) {  // this ensure items with unique names
  return (this[x.name]? false: (this[x.name] = true));
}, {});

document.body.innerHTML = '<pre>' + JSON.stringify(uniqueStandards, 0, 4) + '</pre>';


Alternatively, you could give lodash a try:

var uniqueStandards = _(data).orderBy('lastupdate', 'desc').uniqBy('name').value();

The snipet above uses orderBy() to order the collection by lastupdate in descending order, and uniqBy() to make sure that the collection only has unique names.

var data = [{
  "name": "Alaska",
  "Republican_fre": 3,
  "Democrats_fre": 0,
  "winner": "R",
  "iso_2": "AK",
  "electoral_vote": 3,
  "totalComponents": 3,
  "date": "29.06.2016",
  "lastupdate": "1467233426"
}, {
  "name": "Alabama",
  "Republican_fre": 3,
  "Democrats_fre": 0,
  "winner": "R",
  "iso_2": "AL",
  "electoral_vote": 9,
  "totalComponents": 3,
  "date": "29.06.2016",
  "lastupdate": "1467233426"
}, {
  "name": "Arkansas",
  "Republican_fre": 2,
  "Democrats_fre": 0,
  "winner": "R",
  "iso_2": "AR",
  "electoral_vote": 6,
  "totalComponents": 2,
  "date": "29.06.2016",
  "lastupdate": "1467233426"
}, {
  "name": "Alaska",
  "Republican_fre": 5,
  "Democrats_fre": 0,
  "winner": "R",
  "iso_2": "AK",
  "electoral_vote": 3,
  "totalComponents": 5,
  "date": "29.06.2016",
  "lastupdate": "1467282133"
}];

var uniqueStandards = _(data).orderBy('lastupdate', 'desc').uniqBy('name').value();

document.body.innerHTML = '<pre>' + JSON.stringify(uniqueStandards, 0, 4) + '</pre>';
<script src="https://cdn.jsdelivr.net/lodash/4.13.1/lodash.min.js"></script>

Comments