Question

I have an array of Musical Tracks and in this array the same song can show up multiple times due to being released on multiple albums. I am trying to remove them from the array so that only true uniques show up in the list.

The Hash looks something like this:

"tracks" => [
    [0] {
        "id" => 1,
        "Title" => "Intergalactic",
        "ArtistName" => "Beastie Boys"
    },
    [1] {
        "id" => 2,
        "Title" => "Intergalactic",
        "ArtistName" => "Beastie Boys"
    }
]

I am needing a way to remove the duplicates based on the Title key. Anyway of doing this?

Was it helpful?

Solution

If you are using ActiveSupport, you can use uniq_by, like so :

tracks.uniq_by {|track| track["title"]}

If not, then you can easily implement it yourself. See this.

# File activesupport/lib/active_support/core_ext/array/uniq_by.rb, line 6
  def uniq_by
    hash, array = {}, []
    each { |i| hash[yield(i)] ||= (array << i) }
    array
  end

OTHER TIPS

The Array#uniq! method in 1.9 takes a block so if your Hash is h then:

h['tracks'].uniq! { |x| x['Title'] }

If you're in 1.8 then you can fake it with:

h['tracks'] = h['tracks'].group_by { |x| x['Title'] }.values.map(&:first)

I'm assuming that you want to modify it in-place.

While the other methods are correct, I'll throw in a bit of extra sugar I found elsewhere on SO.

Using this extension of Symbol:

class Symbol
  def with(*args, &block)
    ->(caller, *rest) { caller.send(self, *rest, *args, &block) }
  end
end

Instead of writing simple iterative blocks like

foo_array.each{ |foo| foo.update_bar("baz") }, you can now use

foo_array.each &:update_bar.with("baz")

Similar to how you might write maybe_nil.try(:[], "key")...

foo_array.uniq{ |foo| foo["key"] } is now identical to

foo_array.uniq(&:[].with("key"))

I hope this helps

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top