How to get distinct values from an array of objects in JavaScript?

前端 未结 30 2524
执笔经年
执笔经年 2020-11-22 05:29

Assuming I have the following:

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


        
相关标签:
30条回答
  • 2020-11-22 05:48

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

    0 讨论(0)
  • 2020-11-22 05:48

    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);```
    
    0 讨论(0)
  • 2020-11-22 05:49

    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]
    
    0 讨论(0)
  • 2020-11-22 05:49

    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. ;-)

    0 讨论(0)
  • 2020-11-22 05:51

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

    0 讨论(0)
  • 2020-11-22 05:54

    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]
    
    0 讨论(0)
提交回复
热议问题