Assuming I have the following:
var array =
[
{\"name\":\"Joe\", \"age\":17},
{\"name\":\"Bob\", \"age\":17},
{\"name\":\"Carl\
I've started sticking Underscore in all new projects by default just so I never have to think about these little data-munging problems.
var array = [{"name":"Joe", "age":17}, {"name":"Bob", "age":17}, {"name":"Carl", "age": 35}];
console.log(_.chain(array).map(function(item) { return item.age }).uniq().value());
Produces [17, 35]
.
My below code will show the unique array of ages as well as new array not having duplicate age
var data = [
{"name": "Joe", "age": 17},
{"name": "Bob", "age": 17},
{"name": "Carl", "age": 35}
];
var unique = [];
var tempArr = [];
data.forEach((value, index) => {
if (unique.indexOf(value.age) === -1) {
unique.push(value.age);
} else {
tempArr.push(index);
}
});
tempArr.reverse();
tempArr.forEach(ele => {
data.splice(ele, 1);
});
console.log('Unique Ages', unique);
console.log('Unique Array', data);```
The forEach
version of @travis-j's answer (helpful on modern browsers and Node JS world):
var unique = {};
var distinct = [];
array.forEach(function (x) {
if (!unique[x.age]) {
distinct.push(x.age);
unique[x.age] = true;
}
});
34% faster on Chrome v29.0.1547: http://jsperf.com/filter-versus-dictionary/3
And a generic solution that takes a mapper function (tad slower than direct map, but that's expected):
function uniqueBy(arr, fn) {
var unique = {};
var distinct = [];
arr.forEach(function (x) {
var key = fn(x);
if (!unique[key]) {
distinct.push(key);
unique[key] = true;
}
});
return distinct;
}
// usage
uniqueBy(array, function(x){return x.age;}); // outputs [17, 35]
Here's another way to solve this:
var result = {};
for(var i in array) {
result[array[i].age] = null;
}
result = Object.keys(result);
I have no idea how fast this solution is compared to the others, but I like the cleaner look. ;-)
EDIT: Okay, the above seems to be the slowest solution of all here.
I've created a performance test case here: http://jsperf.com/distinct-values-from-array
Instead of testing for the ages (Integers), I chose to compare the names (Strings).
Method 1 (TS's solution) is very fast. Interestingly enough, Method 7 outperforms all other solutions, here I just got rid of .indexOf() and used a "manual" implementation of it, avoiding looped function calling:
var result = [];
loop1: for (var i = 0; i < array.length; i++) {
var name = array[i].name;
for (var i2 = 0; i2 < result.length; i2++) {
if (result[i2] == name) {
continue loop1;
}
}
result.push(name);
}
The difference in performance using Safari & Firefox is amazing, and it seems like Chrome does the best job on optimization.
I'm not exactly sure why the above snippets is so fast compared to the others, maybe someone wiser than me has an answer. ;-)
I'd just map and remove dups:
var ages = array.map(function(obj) { return obj.age; });
ages = ages.filter(function(v,i) { return ages.indexOf(v) == i; });
console.log(ages); //=> [17, 35]
Edit: Aight! Not the most efficient way in terms of performance, but the simplest most readable IMO. If you really care about micro-optimization or you have huge amounts of data then a regular for
loop is going to be more "efficient".
using ES6
let array = [
{ "name": "Joe", "age": 17 },
{ "name": "Bob", "age": 17 },
{ "name": "Carl", "age": 35 }
];
array.map(item => item.age)
.filter((value, index, self) => self.indexOf(value) === index)
> [17, 35]