Code Review Stack Exchange is a question and answer site for peer programmer code reviews. Join them; it only takes a minute:

Sign up
Here's how it works:
  1. Anybody can ask a question
  2. Anybody can answer
  3. The best answers are voted up and rise to the top

Given a table represented as a javascript array of objects, I would like create a list of unique values for a specific property.

var table = [
  {
    a:1,
    b:2
  },
  {
    a:2,
    b:3
  },
  {
    a:1,
    b:4
  }
];

var groups = _.groupBy(table, "a");
var array = [];
_.forOwn(groups, function(value, key){
  array.push(key);
});

console.log(array);
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/3.10.1/lodash.min.js"></script>
Check your console

The problems with this code is that the groupBy keep track of the values, which I really don't care about, and I need to iterate over the entire list generated by group again so I can yank out the keys. It seems pretty inefficient to me and Im wondering if there is a smarter way to do this without reinventing the wheel (or perhaps if I should just bite the bullet and reinvent the wheel).

share|improve this question

You can always use reduce. Lodash/underscore has a similar function, if compatibility is an important matter.

function getUniqueValuesOfKey(array, key){
  return array.reduce(function(carry, item){
    if(item[key] && !~carry.indexOf(item[key])) carry.push(item[key]);
    return carry;
  }, []);
}

var table = [{
  a:1,
  b:2
},{
  a:2,
  b:3
},{
  a:1,
  b:4
}];

// See snippet result
document.write(JSON.stringify(getUniqueValuesOfKey(table, 'a')));

share|improve this answer

I'm not sure exactly what you're looking for, but here's an implementation in plain Javascript:

var table = [
  {
    a:1,
    b:2
  },
  {
    a:2,
    b:3
  },
  {
    a:1,
    b:4
  }
];

function getUniqueValues(array, key) {
    var result = new Set();
    array.forEach(function(item) {
        if (item.hasOwnProperty(key)) {
            result.add(item[key]);
        }
    });
    return result;
}

log('getUniqueValues(table, "a")');
getUniqueValues(table, "a").forEach(log);

log('getUniqueValues(table, "b")');
getUniqueValues(table, "b").forEach(log);

// utility function to display results in snippet
function log(value) {
    document.write(value + "<br>");
}

share|improve this answer

You could also chain map and filter:

function unique(arr, prop) {
    return arr.map(function(e) { return e[prop]; }).filter(function(e,i,a){
        return i === a.indexOf(e);
    });
}

console.log(unique(table,'a')); //[1,2]
console.log(unique(table,'b')); //[2,3,4]
share|improve this answer

I found out there is an even simpler way to do this. The _.countBy() method does exactly what I want:

var table = [
  {
    a:1,
    b:2
  },
  {
    a:2,
    b:3
  },
  {
    a:1,
    b:4
  }
];


var array = _.countBy(table, function(t){
  return t.a;
});

console.log(array);
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/3.10.1/lodash.min.js"></script>
Check your console

share|improve this answer

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.