How to Remove Duplicates in a Hash in Ruby on Rails

How to remove duplicates in a hash in Ruby on Rails?

I know this is an old thread, but Rails has a method on 'Enumerable' called 'index_by' which can be handy in this case:

list = [
{
:lname => "Brown",
:email => "james@intuit.com",
:fname => "James"
},
{
:lname => nil,
:email => "brad@intuit.com",
:fname => nil
},
{
:lname => "Smith",
:email => "brad@intuit.com",
:fname => "Brad"
},
{
:lname => nil,
:email => "brad@intuit.com",
:fname => nil
},
{
:lname => "Smith",
:email => "brad@intuit.com",
:fname => "Brad"
},
{
:lname => nil,
:email => "brad@intuit.com",
:fname => nil
}
]

Now you can get the unique rows as follows:

list.index_by {|r| r[:email]}.values

To merge the rows with the same email id.

list.group_by{|r| r[:email]}.map do |k, v|
v.inject({}) { |r, h| r.merge(h){ |key, o, n| o || n } }
end

Custom but efficient method:

list.inject({}) do |r, h| 
(r[h[:email]] ||= {}).merge!(h){ |key, old, new| old || new }
r
end.values

How to remove duplicate entries from a hash based on a value

hash_list.to_a
.uniq! { |_, v| v['unit_id'] }
.to_h

But note that, the duplicates are removed only based on the key unit_id.

To do it based on multiple keys,

hash_list.to_a
.uniq! { |_, v| v.values_at('unit_id','_destroy') }
.to_h

Please have a look at Hash#values_at

Output

>> hash_list = { "a"=>{"unit_id"=>"43", "dep_id"=>"153", "_destroy"=>"false"}, "b"=>{"unit_id"=>"43", "dep_id"=>"153", "_destroy"=>"1"}, "c"=>{"unit_id"=>"43", "dep_id"=>"154", "_destroy"=>"false"}, "d"=>{"unit_id"=>"42", "dep_id"=>"154", "_destroy"=>"false"} }
#=> {"a"=>{"unit_id"=>"43", "dep_id"=>"153", "_destroy"=>"false"}, "b"=>{"unit_id"=>"43", "dep_id"=>"153", "_destroy"=>"1"}, "c"=>{"unit_id"=>"43", "dep_id"=>"154", "_destroy"=>"false"}, "d"=>{"unit_id"=>"42", "dep_id"=>"154", "_destroy"=>"false"}}
>> hash_list.to_a.uniq! { |_, v| v.values_at('unit_id','_destroy') }.to_h
#=> {"a"=>{"unit_id"=>"43", "dep_id"=>"153", "_destroy"=>"false"}, "b"=>{"unit_id"=>"43", "dep_id"=>"153", "_destroy"=>"1"}, "d"=>{"unit_id"=>"42", "dep_id"=>"154", "_destroy"=>"false"}}

How to remove duplicate row in array of hashes on Ruby on rails

Here is another group by option

array_of_hashes.group_by {|h| h.values_at("ID","Date")}.transform_values do |v|   
v.find {|r| r["Rate"]}
end

#=> {[100, "2019-05-6"]=>{"Date"=>"2019-05-6", "ID"=>100, "Rate"=>10, "Count"=>1},
# [101, "2019-05-6"]=>{"Date"=>"2019-05-6", "ID"=>101, "Rate"=>25, "Count"=>3},
# [102, "2019-05-6"]=>{"Date"=>"2019-05-6", "ID"=>102, "Rate"=>35, "Count"=>0},
# [103, "2019-05-6"]=>{"Date"=>"2019-05-6", "ID"=>103, "Rate"=>20, "Count"=>6}}

group by id and date then transform the Hash values to the first Hash where "Rate" is not nil.

If multiple values are acceptable then find_all or select could be substituted for find.

If you want the original structure maintained just add values to the end.

How to add hashes to itself and remove duplicates in Ruby?

for Ruby >= 2.4.0 - method #transform_values with methods #inject and #merge

h.transform_values { |v| v.inject(:merge) }

For lower versions:

h.map { |k, v| [k, v.inject(:merge)] }.to_h

Ruby: array of hashes - how to remove duplicates based on the hash key which is an array

So long as your kappa function produces the same value for u,p as for p,u then you can do this:

@result = @user_array.each_with_object({ }) do |u, h|
@user_array.each do |p|
next if (u == p)

h[[u, p].sort] ||= kappa(u, p, "ipf")
end
end

That populates the values once and once only. If you want to do it where the last value sticks then change ||= to =.

Ruby remove duplicate entries in array of hashes but based on more than one value

uniq accepts a block. If a block is given, it will use the return value of the block for comparison.

Your code was close to the solution, but in your code the return value was only a_track[:composer] which is the last evaluated statement.

You can join the attributes you want into a string and return that string.

new_tracks.uniq { |track| [track[:name], track[:artist], track[:composer]].join(":") }

A possible refactoring is

new_tracks.uniq { |track| track.attributes.slice('name', 'artist', 'composer').values.join(":") }

Or add a custom method in your model that performs the join, and call it

class Track < ActiveRecord::Base
def digest
attributes.slice('name', 'artist', 'composer').values.join(":")
end
end

new_tracks.uniq(&:digest)

get rid of duplicates in nested hash

I'm assuming that in the case of { :GE => nil, "GE" => "successful" }, you want to use the first truthy value ("successful") and make sure the key is a symbol:

result = given.transform_values do |inner_hsh|
inner_hsh.group_by do |k,v|
k.to_sym
end.transform_values do |key_vals|
key_vals.to_h.values.find(&:itself)
end
end

How to remove duplicate entry from ruby hash

Just call uniq! method to change hotels array in-place, uniq! takes a block where you can return what you are comparing

hotels.uniq!{|hotel| hotel.id}

e.g. see usage

irb(main):001:0> class Hotel
irb(main):002:1> attr_reader :id
irb(main):002:1> def initialize(id, name)
irb(main):003:2> @id = id
irb(main):004:2> @name = name
irb(main):005:2> end
irb(main):006:1> end
=> nil
irb(main):008:0> hotels = [Hotel.new(1,'one'), Hotel.new(1,'one'), Hotel.new(2,'two'), Hotel.new(2,'two')]
=> [#<Hotel:0x007fa6b9148c48 @id=1, @name="one">, #<Hotel:0x007fa6b9148b58 @id=1, @name="one">, #<Hotel:0x007fa6b9148a40 @id=2, @name="two">, #<Hotel:0x007fa6b9148950 @id=2, @name="two">]
irb(main):013:0> hotels.uniq!{|hotel| hotel.id}
=> [#<Hotel:0x007fa6b9148c48 @id=1, @name="one">, #<Hotel:0x007fa6b9148a40 @id=2, @name="two">]

Delete duplicates from a hash?

Suppose you can retrieve ARL_DISPLAY_NR field from an instance art of ArtLookup like this:

art[:ARL_DISPLAY_NR]

Then you can delete duplicates according to ARL_DISPLAY_NR field by:

hash_array = [ artLookup_foo, artLookup_bar, ... ]

# this will keep the last one in a group of duplicates
Hash[ hash_array.map{|h| [h[:ARL_DISPLAY_NR], h]} ].values

# or keep the first one
Hash[ hash_array.reverse.map{|h| [h[:ARL_DISPLAY_NR], h]} ].values

However, it doesn't guarantee to keep the original order in the previous array.



Related Topics



Leave a reply



Submit