Ruby Hash para matriz de valores

118

Eu tenho isto:

hash  = { "a"=>["a", "b", "c"], "b"=>["b", "c"] } 

e eu quero chegar a este: [["a","b","c"],["b","c"]]

Parece que deveria funcionar, mas não:

hash.each{|key,value| value}
=> {"a"=>["a", "b", "c"], "b"=>["b", "c"]} 

Alguma sugestão?

Tbrooke
fonte
As respostas abaixo estão corretas ( hash.valuessendo a melhor IMO). Mas gostaria de salientar que, quando você fornecer um bloco, Hash#eachele retornará apenas o valor total do hash. Se você quiser fazer uma operação em cada item e retorná-lo como um array, use Hash#collectou seu alias Hash#map. Mais informações sobre Enumerables aqui .
brymck,
3
Esta pergunta parece estranhamente familiar ... Eu me pergunto quantas pessoas estão trabalhando na mesma tarefa de casa agora.
Peter Brown

Respostas:

260

Além disso, um pouco mais simples ....

>> hash = { "a"=>["a", "b", "c"], "b"=>["b", "c"] }
=> {"a"=>["a", "b", "c"], "b"=>["b", "c"]}
>> hash.values
=> [["a", "b", "c"], ["b", "c"]]

Ruby doc aqui

Ray Toal
fonte
3
+! Nifty! Eu irei votar positivamente apesar de ter uma resposta competitiva (usando map), porque gosto muito disso!
Michael Durrant
2
Hash#valuesnão é apenas mais simples, mas também mais eficiente. Compare time ruby -e '(1..1000000).reduce({}){|h,i| h.store i,i; h}.values'comtime ruby -e '(1..1000000).reduce({}){|h,i| h.store i,i; h}.map{|k,v| v}'
jordanbtucker
+1 (Surpreendentemente deslumbrado depois de tentar seu código) Passei um dia sem sorte removendo o índice usando vários métodos ... Tudo o que posso dizer muito obrigado !!! : D
Romanos 8,38-39
2
As chaves estão impressas na ordem exata em que ocorrem?
pilha 1 de
42

Eu usaria:

hash.map { |key, value| value }
Michael Durrant
fonte
3
Eu não votei negativamente, mas é um equivalente mais complicado a Hash#values.
Mark Thomas
1
Sim, eu também votei positivamente na resposta de Ray. Estou feliz por votar positivamente em uma resposta competitiva quando gosto também.
Michael Durrant
3
Acho que não estamos competindo aqui e sim nos ajudando, certo? :)
witkacy26
Exatamente o que eu estava procurando ao tentar criar um array a partir de um hash usando suas chaves como valores. Obrigado :)
Fabian Leutgeb
Útil quando você precisa fazer alguma lógica com as chaves ao mesmo tempo.
Chris Cirefice
22
hash.collect { |k, v| v }
#returns [["a", "b", "c"], ["b", "c"]] 

Enumerable#collectpega um bloco e retorna uma matriz dos resultados da execução do bloco uma vez em cada elemento do enumerável. Portanto, este código apenas ignora as chaves e retorna uma matriz de todos os valores.

O Enumerablemódulo é muito bom. Conhecê-lo bem pode economizar muito tempo e muito código.

Jergason
fonte
2
Não se esqueça que, como a resposta de @Ray Toal, hash.valuesé , em última análise, a resposta correta aqui.
tadman
Ou hash.map(&:second):)
Jaap Haagmans
7
hash  = { :a => ["a", "b", "c"], :b => ["b", "c"] }
hash.values #=> [["a","b","c"],["b","c"]]
mrded
fonte
stackoverflow.com/posts/12771873/revisions como você pode ver, a formatação do seu código estava muito
errada
4

É tão simples quanto

hash.values
#=> [["a", "b", "c"], ["b", "c"]]

isso retornará uma nova matriz preenchida com os valores do hash

se você quiser armazenar essa nova matriz, faça

array_of_values = hash.values
#=> [["a", "b", "c"], ["b", "c"]]

array_of_values
 #=> [["a", "b", "c"], ["b", "c"]]
Melissa Quintero
fonte
2

Existe também este:

hash = { foo: "bar", baz: "qux" }
hash.map(&:last) #=> ["bar", "qux"]

Por que funciona:

A &chama to_procno objecto, e passa-o como um bloco para o método.

something {|i| i.foo }
something(&:foo)
Karlingen
fonte
Uma explicação mais detalhada brianstorti.com/understanding-ruby-idiom-map-with-symbol
Sylvain