Reputation: 3243
I want to output an array of hashes with the name
being unique to all hashes. How would I go about doing this using ruby?
This is my input:
input = [{:name => "Kutty", :score => 2, :some_key => 'value', ...},
{:name => "Kutty", :score => 4, :some_key => 'value', ...},
{:name => "Baba", :score => 5, :some_key => 'value', ...}]
I want the output to look like this:
output = [{:name => "Kutty", :score => 4, :some_key => 'value', ...},
{:name => "Baba", :score => 5, :some_key => 'value', ...}]
Upvotes: 7
Views: 6731
Reputation: 821
Try this solution..
input = [{:name => "Kutty", :score => 2, :some_key => 'value'},
{:name => "Kutty", :score => 4, :some_key => 'value'},
{:name => "Baba", :score => 5, :some_key => 'value'}]
a = []
output = []
input.collect do |i|
input.delete(i) if !a.include?(i[:name])
output << i if !a.include?(i[:name])
a << i[:name] if !a.include?(i[:name])
end
output = [{:some_key=>"value", :name=>"Kutty", :score=>2},
{:some_key=>"value", :name=>"Baba", :score=>5}]
UPDATED
output = {}
input.each do |e|
ref = output[e[:name]]
if ref && ref[:score] > e[:score]
#nothing
else
output[e[:name]] = e
end
end
check output:
puts output.values
Upvotes: 4
Reputation: 181097
To just remove duplicates based on :name, simply try;
output = input.uniq { |x| x[:name] }
Demo here.
Edit: Since you added a sorting requirement in the comments, here's how to select the entry with the highest score for every name if you're using Rails, I see you already got an answer for "standard" Ruby above;
output = input.group_by { |x| x[:name] }
.map {|x,y|y.max_by {|x|x[:score]}}
A little explanation may be in order; the first line groups
the entries by name so that each name gets its own array of entries. The second line goes through the groups, name by name, and maps
each name group to the entry with the highest score.
Demo here.
Upvotes: 17
Reputation: 1294
input = [{:name => "Kutty", :score => 2, :some_key => 'value'},{:name => "Kutty", :score => 4, :some_key => 'value'},{:name => "Baba", :score => 5, :some_key => 'value'}]
p input.uniq { |e| e[:name] }
The above solution works for ruby > 1.9, for older versions of ruby you could use something along these lines:
input = [{:name => "Kutty", :score => 2, :some_key => 'value'},{:name => "Kutty", :score => 4, :some_key => 'value'},{:name => "Baba", :score => 5, :some_key => 'value'}]
unames = []
new_input = input.delete_if { |e|
if unames.include?(e[:name])
true
else
unames << e[:name]
false
end
}
p new_input
Upvotes: 4