2009-11-06 4 views
6

Для удобства я пытаюсь назначить несколько значений хэш-ключу в Ruby. Вот код до сих порКак назначить несколько значений хэшированию?

myhash = { :name => ["Tom" , "Dick" , "Harry"] } 

Перебор хэш дает каскадный строка из 3 значений

Выход:

name : TomDickHarry 

Обязательный выход:

:name => "Tom" , :name => "Dick" , :name => "Harry" 

Какой код должен Я пишу, чтобы получить требуемый результат?

ответ

4

Вы создали хеш с именем символа в качестве ключа и массивом с тремя элементами в качестве значения, поэтому вам нужно выполнить итерацию через myhash[:name], чтобы получить отдельные элементы массива.

6
myhash.each_pair {|k,v| v.each {|n| puts "#{k} => #{n}"}} 
#name => Tom 
#name => Dick 
#name => Harry 

Формат вывода не совсем то, что вам нужно, но я думаю, что вы поняли эту идею.

+0

@pierr, спасибо. У меня есть более 1 ключа в этом хэше и хочу перебирать выборочные ключи, для этого я пытаюсь использовать Hash [* myhash.select {| k, v | [: name] .include? (k)}. flatten], но получив ошибку, что я делаю неправильно? –

+0

Причина ошибки в том, что flatten является рекурсивным, поэтому вы получаете 1 длинный список, а не список пар ключей и значений. – mikej

5

Ответы Rohith и pierr в этом случае прекрасны. Однако, если это то, что вы собираетесь широко использовать, стоит знать, что структура данных, которая ведет себя как Hash, но допускает несколько значений для ключа, обычно называется мультимапом. Для Ruby существует несколько реализаций, включая this one.

+0

Ссылка мертва: http://github.com/josh/multimap – wisbucky

3

re: проблема итерации по селективным клавишам. Попробуйте использовать reject с условием инвертированного вместо select.

например. Дано:

{:name=>["Tom", "Dick", "Harry"], :keep=>[4, 5, 6], :discard=>[1, 2, 3]} 

, где мы хотим :name и :keep но не :discard

с select:

myhash.select { |k, v| [:name, :keep].include?(k) } 
=> [[:name, ["Tom", "Dick", "Harry"]], [:keep, [4, 5, 6]]] 

Результатом является список пар.

но с reject:

myhash.reject { |k, v| ![:name, :keep].include?(k) } 
=> {:name=>["Tom", "Dick", "Harry"], :keep=>[4, 5, 6]} 

В результате Hash только записи, которые вы хотите.

Это может быть в сочетании с ответом pierr в:

hash_to_use = myhash.reject { |k, v| ![:name, :keep].include?(k) } 
hash_to_use.each_pair {|k,v| v.each {|n| puts "#{k} => #{n}"}} 
Смежные вопросы