How to get distinct values from an array of object

2019-01-01 08:08发布

Assuming I have the following:

var array = 
    [
        {"name":"Joe", "age":17}, 
        {"name":"Bob", "age":17}, 
        {"name":"Carl", "age": 35}
    ]

What is the best way to be able to get an array of all of the distinct ages such that I get an result array of:

[17, 35]

Is there some way I could alternatively structure the data or better method such that I would not have to iterate through each array checking the value of "age" and check against another array for its existence, and add it if not?

If there was some way I could just pull out the distinct ages without iterating...

Current inefficent way I would like to improve... If it means that instead of "array" being an array of objects, but a "map" of objects with some unique key (i.e. "1,2,3") that would be okay too. Im just looking for the most performance efficient way.

The following is how I currently do it, but for me, iteration appears to just be crummy for efficiency even though it does work...

var distinct = []
for (var i = 0; i < array.length; i++)
   if (array[i].age not in distinct)
      distinct.push(array[i].age)

27条回答
低头抚发
2楼-- · 2019-01-01 08:40

i think you are looking for groupBy function (using Lodash)

_personsList = [{"name":"Joe", "age":17}, 
                {"name":"Bob", "age":17}, 
                {"name":"Carl", "age": 35}];
_uniqAgeList = _.groupBy(_personsList,"age");
_uniqAges = Object.keys(_uniqAgeList);

produces result:

17,35

jsFiddle demo:http://jsfiddle.net/4J2SX/201/

查看更多
永恒的永恒
3楼-- · 2019-01-01 08:40
var unique = array
    .map(p => p.age)
    .filter((age, index, arr) => arr.indexOf(age) == index)
    .sort();

// or

var unique = [...new Set(array.map(p => p.age))];
查看更多
笑指拈花
4楼-- · 2019-01-01 08:41

If this were PHP I'd build an array with the keys and take array_keys at the end, but JS has no such luxury. Instead, try this:

var flags = [], output = [], l = array.length, i;
for( i=0; i<l; i++) {
    if( flags[array[i].age]) continue;
    flags[array[i].age] = true;
    output.push(array[i].age);
}
查看更多
何处买醉
5楼-- · 2019-01-01 08:41

Just found this and I thought it's useful

_.map(_.indexBy(records, '_id'), function(obj){return obj})

Again using underscore, so if you have an object like this

var records = [{_id:1,name:'one', _id:2,name:'two', _id:1,name:'one'}]

it will give you the unique objects only.

What happens here is that indexBy returns a map like this

{ 1:{_id:1,name:'one'}, 2:{_id:2,name:'two'} }

and just because it's a map, all keys are unique.

Then I'm just mapping this list back to array.

In case you need only the distinct values

_.map(_.indexBy(records, '_id'), function(obj,key){return key})

Keep in mind that the key is returned as a string so, if you need integers instead, you should do

_.map(_.indexBy(records, '_id'), function(obj,key){return parseInt(key)})
查看更多
素衣白纱
6楼-- · 2019-01-01 08:41

Just try

var x = [] ;
for (var i = 0 ; i < array.length ; i++)
{
 if(x.indexOf(array[i]['age']) == -1)
  {
    x.push(array[i]['age']);
  }
}
console.log(x);
查看更多
余生请多指教
7楼-- · 2019-01-01 08:43

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".

查看更多
登录 后发表回答