Como faço para classificar uma matriz de hashes por um valor no hash?

120

Este código Ruby não está se comportando como eu esperava:

# create an array of hashes
sort_me = []
sort_me.push({"value"=>1, "name"=>"a"})
sort_me.push({"value"=>3, "name"=>"c"})
sort_me.push({"value"=>2, "name"=>"b"})

# sort
sort_me.sort_by { |k| k["value"]}

# same order as above!
puts sort_me

Estou tentando classificar a matriz de hashes pela chave "valor", mas eles são impressos sem classificação.

Ollie Glass
fonte

Respostas:

215

Ruby sortnão classifica no local. (Você tem experiência em Python, talvez?)

Ruby tem sort!para classificação in-loco, mas não há variante in-loco para sort_byno Ruby 1.8. Na prática, você pode fazer:

sorted = sort_me.sort_by { |k| k["value"] }
puts sorted

A partir do Ruby 1.9+, .sort_by!está disponível para classificação no local:

sort_me.sort_by! { |k| k["value"]}
Stéphan Kochen
fonte
28
Na verdade, Array#sort_by!é novo no Ruby 1.9.2. Disponível hoje para todas as versões Ruby exigindo minha backportsgema também :-)
Marc-André Lafortune
Olá, também há uma maneira de classificar em ordem decrescente? Acho que posso querer ir 3,2,1...
tekknolagi
2
Você não pode fazer isso com sort_by, mas use sortou sort!e simplesmente inverta os operandos: a.sort! {|x,y| y <=> x }( ruby-doc.org/core-1.9.3/Array.html#method-i-sort )
Stéphan Kochen
1
Ou:puts sorted = sort_me.sort_by{ |k,v| v }
Zaz
9
@tekknolagi: Basta anexar .reverse.
Zaz
21

De acordo com @shteef, mas implementado com a sort!variante conforme sugerido:

sort_me.sort! { |x, y| x["value"] <=> y["value"] }
bjg
fonte
7

Embora Ruby não tenha uma sort_byvariante local, você pode fazer:

sort_me = sort_me.sort_by { |k| k["value"] }

Array.sort_by! foi adicionado em 1.9.2

AG_
fonte
1
Esta resposta "Array.sort_by! Foi adicionado em 1.9.2" funcionou para mim
web spider
2

Você pode usar sort_me.sort_by!{ |k| k["value"]}. Isso deve funcionar.

Mukesh Kumar Gupta
fonte