Ruby removing duplicates from array based on key=>value
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?
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
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
精彩评论