Array#Uniq with Block Equivalent in Ruby 1.8.7

Array#uniq with block equivalent in Ruby 1.8.7

Install Marc-André LaFortune's backports gem:

https://github.com/marcandre/backports

That has the block versions of 1.9.2's Array#uniq and Array#uniq!. Or if you don't want or need the whole thing, the parts are pretty well isolated so you can pull out just the pieces you need:

https://github.com/marcandre/backports/blob/master/lib/backports/1.9.2/array.rb#L99

Extending uniq method

It already works for me in 1.8.7.

1:~$ ruby -v
ruby 1.8.7 (2008-08-11 patchlevel 72) [i486-linux]
1:~$ irb -v
irb 0.9.5(05/04/13)
1:~$ irb
>> [{"three"=>"3"}, {"three"=>"4"}, {"three"=>"3"}].uniq
=> [{"three"=>"3"}, {"three"=>"4"}]

Remove similar objects from array

Unfortunately, uniq_by isn't available in Ruby core. Pull it in with require 'activesupport'.

items.uniq_by {|h| [h[:replationship_1], h[:value]] }

Edit: As noted by @mu below, Ruby 1.9's uniq also works:

items.uniq{|h| [h[:replationship_1], h[:value]] }

Difference in output between Ruby versions when running script

I get same results for both version (1.8, 1.9.3)

$ ruby1.8 --version
ruby 1.8.7 (2012-02-08 patchlevel 358) [i686-linux]
$ ruby1.9.3 --version
ruby 1.9.3p194 (2012-04-20 revision 35410) [i686-linux]
$ ruby1.8 t.rb
9183
$ ruby1.9.3 t.rb
9183

BTW, chaining uniq! with count is not a good idea, because uniq! returns nil if there's no duplicate.

Fastest/One-liner way to remove duplicates (by key) in Ruby Array?

Here's the standard hashy way. Note the use of ||= operator, which is a more convenient (a ||= b) way to write a = b unless a.

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

You can do it in a single line either.

The script needs O(n) equality checks of text strings. That's what's covered under O(n) when you see a hash.

Issues with DISTINCT when used in conjunction with ORDER

If you're on Ruby 1.9.2+, you can use Array#uniq and pass a block specifying how to determine uniqueness. For example:

@unique_results = @filtered_names.uniq { |result| result.athlete_id }

That should return only one result per athlete, and that one result should be the first in the array, which in turn will be the quickest time since you've already ordered the results.

One caveat: @filtered_names might still be an ActiveRecord::Relation, which has its own #uniq method. You may first need to call #all to return an Array of the results:

@unique_results = @filtered_names.all.uniq { ... }


Related Topics



Leave a reply



Submit