The fastest / single-line way to remove duplicates (by key) in Ruby Array?

What is the fastest / single-line way to remove duplicates in an array of objects based on a specific key: value or result returned by the method?

For example, I have 20 XML Element nodes that have the same name, but they have different “text” values, some of which are duplicate. I would like to remove duplicates by saying "if element.text == previous_element.text, delete it". How to do it in Ruby in the shortest amount of code?

I saw how to do this for simple string / integer values, but not for objects.

+7
arrays ruby duplicates
source share
3 answers

Here's the standard hash path. Note the use of the ||= operator, which is a more convenient ( a ||= b ) way of writing a = b unless a .

 array.inject({}) do |hash,item| hash[item.text]||=item hash end.values.inspect 

You can do this in one line.

The script requires equality checks (t) for text strings. What is covered under O (n) when you see a hash.

+14
source share

It does everything:

 Hash[*a.map{|x| [x.text, x]}].values 

short? Yeah.

(an asterisk is optional, it appears to be required for 1.8.6).

For example:

 a = [Thing.new('a'), Thing.new('b'), Thing.new('c'), Thing.new('c')] => [#<Thing a>, #<Thing b>, #<Thing c>, #<Thing c>] Hash[a.map{|x| [x.text, x]}].values => [#<Thing a>, #<Thing b>, #<Thing c>] 

The boring part: here is a small class of tests that I used:

 class Thing attr_reader :text def initialize(text) @text = text end def inspect "#<Thing #{text}>" end end 
+10
source share

Use Array#uniq with a block. In your case:

 array.uniq(&:text) # => array with duplicated `text` removed 

This was introduced in Ruby 1.9.2, so if you use an earlier version, you can use backports with require 'backports/1.9.2/array/uniq'

+4
source share

All Articles