Czy byłby to najlepszy sposób na posortowanie skrótu i zwrócenie obiektu Hash (zamiast Array):
h = {"a"=>1, "c"=>3, "b"=>2, "d"=>4}
# => {"a"=>1, "c"=>3, "b"=>2, "d"=>4}
Hash[h.sort]
# => {"a"=>1, "b"=>2, "c"=>3, "d"=>4}
Czy byłby to najlepszy sposób na posortowanie skrótu i zwrócenie obiektu Hash (zamiast Array):
h = {"a"=>1, "c"=>3, "b"=>2, "d"=>4}
# => {"a"=>1, "c"=>3, "b"=>2, "d"=>4}
Hash[h.sort]
# => {"a"=>1, "b"=>2, "c"=>3, "d"=>4}
Odpowiedzi:
W Ruby 2.1 jest to proste:
h.sort.to_h
h.sort{|a,z|a<=>z}.to_h
(testowane 2.1.10, 2.3.3)
a
to tablica, nie tylko klucz). Usunąłem mój komentarz.
h.map(&:sort).map(&:to_h)
.
Uwaga: Ruby> = 1.9.2 ma hash zachowujący porządek: wstawiane klucze zamówień będą kolejnością, w której są wyliczane. Poniższe dotyczy starszych wersji lub kodu kompatybilnego wstecz.
Nie ma koncepcji posortowanego skrótu. Więc nie, to co robisz jest niewłaściwe.
Jeśli chcesz posortować do wyświetlenia, zwróć ciąg:
"{" + h.sort.map{|k,v| "#{k.inspect}=>#{v.inspect}"}.join(", ") + "}"
lub, jeśli chcesz klucze w kolejności:
h.keys.sort
lub, jeśli chcesz uzyskać dostęp do elementów w kolejności:
h.sort.map do |key,value|
# keys will arrive in order to this block, with their associated value.
end
ale podsumowując, nie ma sensu mówić o posortowanym haszu. Z dokumentów : „Kolejność przechodzenia przez skrót lub klucz lub wartość może wydawać się dowolna i na ogół nie będzie w kolejności wstawiania”. Więc wstawienie kluczy w określonej kolejności do skrótu nie pomoże.
Zawsze używałem sort_by
. Musisz owinąć dane #sort_by
wyjściowe, Hash[]
aby uzyskać wynik mieszania, w przeciwnym razie wyprowadza tablicę tablic. Alternatywnie, aby to osiągnąć, możesz uruchomić #to_h
metodę na tablicy krotek, aby przekonwertować je na k=>v
strukturę (skrót).
hsh ={"a" => 1000, "b" => 10, "c" => 200000}
Hash[hsh.sort_by{|k,v| v}] #or hsh.sort_by{|k,v| v}.to_h
Podobne pytanie znajduje się w „ Jak posortować Ruby Hash według wartości liczbowej? ”.
sort_by
skrótu zwróci tablicę. Będziesz musiał ponownie zmapować go jako skrót. Hash[hsh.sort_by{|k,v| v}]
hsh.sort_by(&:last).to_h => {"b"=>10, "a"=>1000, "c"=>200000}
.
to_h
jest obsługiwane tylko w Ruby 2.1.0+
sort_by{|k,v| v}.to_h)
Nie, to nie jest (Ruby 1.9.x)
require 'benchmark'
h = {"a"=>1, "c"=>3, "b"=>2, "d"=>4}
many = 100_000
Benchmark.bm do |b|
GC.start
b.report("hash sort") do
many.times do
Hash[h.sort]
end
end
GC.start
b.report("keys sort") do
many.times do
nh = {}
h.keys.sort.each do |k|
nh[k] = h[k]
end
end
end
end
user system total real
hash sort 0.400000 0.000000 0.400000 ( 0.405588)
keys sort 0.250000 0.010000 0.260000 ( 0.260303)
W przypadku dużych skrótów różnica wzrośnie do 10x i więcej
Dałeś najlepszą odpowiedź sobie w OP: Hash[h.sort]
jeśli pragniesz więcej możliwości, oto modyfikacja oryginalnego skrótu na miejscu, aby go posortować:
h.keys.sort.each { |k| h[k] = h.delete k }
Sortuj skrót według klucza , zwróć skrót w Ruby
Z destrukcją i sortowaniem Hash
hash.sort { |(ak, _), (bk, _)| ak <=> bk }.to_h
Wyliczalny # sort_by
hash.sort_by { |k, v| k }.to_h
Hash # sortuj z zachowaniem domyślnym
h = { "b" => 2, "c" => 1, "a" => 3 }
h.sort # e.g. ["a", 20] <=> ["b", 30]
hash.sort.to_h #=> { "a" => 3, "b" => 2, "c" => 1 }
Uwaga: <Ruby 2.1
array = [["key", "value"]]
hash = Hash[array]
hash #=> {"key"=>"value"}
Uwaga:> Ruby 2.1
[["key", "value"]].to_h #=> {"key"=>"value"}
v
, hash.sort_by { |k, _v| k }.to_h
ActiveSupport :: OrdersHash to kolejna opcja, jeśli nie chcesz używać Ruby 1.9.2 lub tworzyć własnych obejść.
@ordered = {}
@unordered.keys.sort.each do |key|
@ordered[key] = @unordered[key]
end
Miałem ten sam problem (musiałem posortować sprzęt według nazwy) i rozwiązałem w ten sposób:
<% @equipments.sort.each do |name, quantity| %>
...
<% end %>
@equipments to skrót, który buduję na moim modelu i zwracam na kontrolerze. Jeśli wywołasz .sort, posortuje skrót według jego kluczowej wartości.
Podobało mi się rozwiązanie we wcześniejszym poście.
Zrobiłem mini-klasę class AlphabeticalHash
. Ma również sposób zwany ap
, która przyjmuje jeden argument, Hash
jako wejście: ap variable
. Podobne do pp ( pp variable
)
Ale to (spróbuje) wydrukować na liście alfabetycznej (jej klucze). Nie wiem, czy ktokolwiek chce tego użyć, jest dostępny jako klejnot, możesz go zainstalować w ten sposób:gem install alphabetical_hash
Dla mnie jest to dość proste. Jeśli inni potrzebują więcej funkcji, daj mi znać, włączę ją do klejnotu.
EDYCJA: Podziękowania należą się Peterowi , który podsunął mi pomysł. :)
each
lubeach_pair
iterujesz. Nawet wtedy pewnie nadal chwytałbym klucze, sortowałam je, a następnie powtarzałam je, chwytając wartości w razie potrzeby. To gwarantuje, że kod będzie działał poprawnie na starszych Rubinach.