Как удалить дубликаты из массива хэшей только на основе ключей?

#ruby #hash

#ruby #хэш

Вопрос:

Как бы вы поступили с удалением дубликатов на основе ключа?

 values = [{"a"=>"1"}, {"a"=>"2"}, {"b"=>"1"}, {"a"=>"4"}]
  

Как я могу игнорировать значение и запускать uniq на основе ключа, чтобы он возвращал:

 [{'a' => '1'}, {'b' => '1'}]
  

Комментарии:

1. @sawa, работающий под управлением 1.8.7, мой irb принял их просто отлично, но я обновил сообщение, чтобы все было менее запутанным.

2. Ладно, извините. Ваше предположение верно. Я использую ruby1.9.2.

Ответ №1:

Предполагая, что вам все равно, какое значение будет заблокировано, просто запустите их в хэш (который имеет уникальные ключи и поэтому, вероятно, является подходящим классом коллекции для этого случая):

 h = {}
values.each{|i|i.each{|k,v|h[k] = v}}
puts h # => {"a"=>"4", "b"=>"1"}
  

… или, если вы хотите, чтобы первый из каждого ключа:

 h = {}
values.each{|i|i.each{|k,v|h[k] = v unless h[k]}}
  

Если вы хотите вернуться к массиву:

 h.each{|k,v|a << {k=>v}}
  

Ответ №2:

Следующее будет работать только в ruby 1.9, так что это может быть бесполезно.

 Hash[values.map(amp;:first).reverse].map{|a| Hash[*a]}
  

Если вам это нужно в исходном порядке,

 values amp; Hash[values.map(amp;:first).reverse].map{|a| Hash[*a]}
  

Ответ №3:

Без введения каких-либо промежуточных переменных следующая строка 1 сделает свое дело:

 > [{"a"=>"1"}, {"a"=>"2"}, {"b"=>"1"}, {"a"=>"4"}].inject({}) {|s,h| s.merge(h) unless s.keys.include? h.keys}.inject([]) {|s,h| s << {h[0]=>h[1]}}
 => [{"a"=>"4"}, {"b"=>"1"}]