Reputation: 6394
What is a fast way of making a Javascript array unique by attribute?
I have an array sorted by timestamp, like this:
[
{
ts: 1417048100,
release: 1.0
},
{
ts: 1417046900,
release: 1.1
},
{
ts: 1417046712,
release: 1.0
}
]
And I want to make it unique by release number, keeping only the ones with the latest timestamp. In my example, that would mean removing the last entry since there is a newer one for that release.
Upvotes: 3
Views: 886
Reputation: 20014
You can use Array.prototype.reduce along with Array.prototype.some like:
var items = [{ts: 1417048100,release: 1.0},{ts: 1417046900,release: 1.1},{ts: 1417046712,release: 1.0}];
var results = items.reduce(function(res, item){
var exists = res.some(function(t){ return (t.release === item.release );});
if (!exists){
res.push(item);
}
return res; },[]);
document.body.innerHTML = '<pre>' + JSON.stringify(results) + '</pre>';
Array.prototype.some allows you to check whether or not the item exists in the array and if it does it is not included in the Array.prototype.reduce res.push(item);
while processing of the array.
If you are open to use other libraries you may be interested in checking lo-dash unique:
Upvotes: 0
Reputation: 1
Try
var arr = [
{
ts: 1417048100,
release: 1.0
},
{
ts: 1417046900,
release: 1.1
},
{
ts: 1417046712,
release: 1.0
}
]
, arr = arr.sort(function(a, b) {
return (a.ts > b.ts) ? -1 : 1
}).filter(function(val, key) {
return $.inArray(val.release, arr.map(function(v) {return v.release})) === key
});
var arr = [
{
ts: 1417048100,
release: 1.0
},
{
ts: 1417046900,
release: 1.1
},
{
ts: 1417046712,
release: 1.0
}
]
, arr = arr.sort(function(a, b) {
return (a.ts > b.ts) ? -1 : 1
}).filter(function(val, key) {
return $.inArray(val.release, arr.map(function(v) {return v.release})) === key
});
$.each(arr, function(k, v) {
$("<span>").html("release:" + v.release + ", timestamp:" + v.ts + "<br />")
.appendTo("body")
})
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
Upvotes: 0
Reputation: 168
if you can use jquery then try with grep
var releases =[
{
ts: 1417048100,
release: 1.0
},
{
ts: 1417046900,
release: 1.1
},
{
ts: 1417046712,
release: 1.0
}];
var newRelease={
ts: 1517046712,
release: 1.0
};
releases = jQuery.grep(y, function(value) {
return value.release != newRelease.release;
});
releases.push(newRelease);
Upvotes: 0
Reputation: 318202
You could iterate over the array with forEach
and store the release numbers in an object to make sure that any releases already iterated over are spliced out of the array.
var arr = [{
ts: 1417048100,
release: 1.0
},
{
ts: 1417046900,
release: 1.1
},
{
ts: 1417046712,
release: 1.0
}];
var o = {};
arr.forEach(function(x, i) {
if (x.release in o) arr.splice(i, 1);
o[x.release] = null;
});
document.body.innerHTML = '<pre>' + JSON.stringify(arr, null, 4) + '</pre>';
Upvotes: 2
Reputation: 2865
Convert the array into an associative array. The keys in an associative array are unique. Example code shown in node.
→ node
> a ={ "1.0": 1417048100, "1.1": 1417046900}
{ '1.0': 1417048100,
'1.1': 1417046900 }
> a["1.0"]
1417048100
> a["1.0"]=99999
99999
> a
{ '1.0': 99999,
'1.1': 1417046900 }
For a better understanding read up on hashes and the blog post below may also be helpful.
http://www.javascriptkata.com/2007/03/29/how-to-use-javascript-hashes/
Upvotes: -1
Reputation: 137312
Convert it to a mapping, using the release
as the key.
var output = {};
for(var i=0; i<input.length; i++) {
output[input[i].release] = input[i].ts;
}
It will automatically overwrite older release keys with newer release keys.
If you need it to remain sorted, then you would need to re-convert it to a list and sort it, or filter the original list down by only the remaining output keys.
Upvotes: 1