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
Example. { "name":"John", "age":30, "car":null } JSON objects are surrounded by curly braces {}. JSON objects are written in key/value pairs. Keys must be strings, and values must be a valid JSON data type (string, number, object, array, boolean or null). Keys and values are separated by a colon.
Each key/value pair is separated by a comma. It is a common mistake to call a JSON object literal "a JSON object". JSON cannot be an object. JSON is a string format.
Keys and values are separated by a colon. Each key/value pair is separated by a comma. Values in a JSON object can be another JSON object. You can access nested JSON objects by using the dot notation or bracket notation:
Comparing two objects like this results in false even if they have the same data. It is because those are two different object instances, they are referring to two different objects. There is no direct method in javascript to check whether two objects have the same data or not.
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>
Here's one approach. Create object using name as keys and update object based on lastUpdate, then map object to array
function arrUnique(arr){
var tmp={};
arr.forEach(function(item) {
if(!tmp[item.name] || +item.lastupdate > +tmp[item.name].lastupdate){
tmp[item.name] = item ;
}
});
return Object.keys(tmp).map(function(key){
return tmp[key]
});
}
Note that string comparisons of your lastUpdate may not return correct results which is why I cast to number
DEMO
I hope I understand you correctly.
You want to get the output arrayof distinct values ordered by max(lastupdate).
This code works as I described.It called grouping of arrays
var group = [];
arr.forEach(function(val, key)
{
if(!group[val.name])
group[val.name] = val;
else{
if(group[val.name].lastupdate < val.lastupdate)
group[val.name] = val;
}
}
);
console.log(group);
I seriously doubt that JSON is the best format to apply that operation to.
If you really need to use JSON than it is for the best to check that on input, and to overwrite attribute (or just the date). In that case you could make sure that no duplicate exists.
If you had arbitrary values in strings and you searched for duplicates this is a really tricky task. The obvious solution would be to order it and then search for dupes in O(nlogn) time. If we use hash that problem can be solved in O(n) complexity.
But knowing that you have a known number of states you should iterate trough array for each state.
foreach state in states
var choosenOne = {}
foreach item in array
if(choosenOne == {}) {
choosenOne = item;
} else {
if(item.name == state) {
if(choosenOne.lastupdate > item.lastupdate)
delete item;
} else {
delete choosenOne
choosenOne = item;
}
}
This is just the algorithm that should provide you a solution in O(50*n) ~ O(n)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With