Reputation: 1221
I have an array of hashes where each hash is a list of URL parameters from URI::decode_www_form. I want to remove duplicates in this array so that all hashes inside the array have unique parameter keys.
For example if I have
arr = [{"update" => "1", "reload" => "true"},
{"update" => "5", "reload" => "false"},
{"update" => "9", "reload" => "false"},
{"update" => "7", "reload" => "true", "newvalue" => "11111"},
{"page" => "1"}]
I would expect to have an array containing only:
arr = [{"update" => "1", "reload" => "true"},
{"update" => "7", "reload" => "true", "newvalue" => "11111"},
{"page" => "1"}]
Where the first three entries are duplicates of each other so only keep one of them, the fourth being unique since it has an extra unique key the first three did not have, and the fifth being unique since it is not the same as any of them.
How would I attempt to solve this problem?
Upvotes: 0
Views: 176
Reputation: 110755
arr = [{"update" => "1", "reload" => "true"},
{"update" => "5", "reload" => "false"},
{"update" => "9", "reload" => "false"},
{"update" => "7", "reload" => "true", "newvalue" => "11111"},
{"page" => "1"}]
arr.uniq(&:keys)
#=> [{"update"=>"1", "reload"=>"true"},
# {"update"=>"7", "reload"=>"true", "newvalue"=>"11111"},
# {"page"=>"1"}]
See the doc for Array#uniq for the case where uniq
takes a block. In effect, Ruby is doing the following to determine which elements of arr
to select:
a = arr.map(&:keys)
#=> [["update", "reload"],
# ["update", "reload"],
# ["update", "reload"],
# ["update", "reload", "newvalue"],
# ["page"]]
a.uniq
#=> [["update", "reload"], ["update", "reload", "newvalue"], ["page"]]
arr.uniq(&:keys)
has the same effect as:
arr.uniq { |h| h.keys }
#=> [{"update"=>"1", "reload"=>"true"},
# {"update"=>"7", "reload"=>"true", "newvalue"=>"11111"},
# {"page"=>"1"}]
Many view arr.uniq(&:keys)
as just a short-hand way of writing the above expression with the block. That's OK, but actually arr.uniq(&:keys)
converts the method (represented by the symbol) :keys
to a proc and then calls the proc.
Upvotes: 1
Reputation: 3032
You could solve it like this:
tmp = {}
b = arr.select do |h|
if tmp[h.keys]
false
else
tmp[h.keys] = true
true
end
end
Upvotes: 1