kabal
kabal

Reputation: 2145

ember.js - extract distinct properties from array

lets say I have the following array, and this is used in my controller

songs = [
  {trackNumber: 4, title: 'Ob-La-Di, Ob-La-Da', genre: 'pop'},
  {trackNumber: 2, title: 'Back in the U.S.S.R.', genre: 'rock'},
  {trackNumber: 3, title: 'Glass Onion', genre: 'pop'},
];

I would like to have a property on my controller that returns an array of unique genres

eg

genres: function() {
  ...
}...

and in this case would return

['pop', 'rock']

is there some elegant way to do this with ember, using computed properties an or observers?

Upvotes: 9

Views: 5942

Answers (1)

Frances McMullin
Frances McMullin

Reputation: 5706

My original answer is at the bottom, but the latest Ember releases provide a really nice new solution for this:

genres: Ember.computed.mapBy('songs', 'genre'),
uniqueGenres: Ember.computed.uniq('genres'),

References: mapBy and uniq. Computed property macros are great =)

previous answer:

genres: function() {
  return this.get('songs').map(function(song){
    return song.genre
  }).filter(function(genre, index, arr){
    return arr.indexOf(genre) == index // throw away any instances which are not first
  })
}.property('songs'),

note, I'm leveraging 'modern' array functions such as map and filter here, if you need to support older browsers, you'll need to shim those or write this another way. The filter I used for removing duplicates is the first that occurred to me, it's probably not very performant and if you've already loaded a library with a unique function (like underscore.uniq), you should use that.

Very little of this is Ember specific of course, the .property('songs') on the end is literally all you need to specify that this is a computed property, which will be cached and recomputed if songs changes (assumes Ember 1.0)

References: MDN for map and filter

Upvotes: 20

Related Questions