Це був би найкращий спосіб сортувати хеш і повертати об’єкт Hash (замість масиву):
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}
Це був би найкращий спосіб сортувати хеш і повертати об’єкт Hash (замість масиву):
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}
Відповіді:
У Ruby 2.1 це просто:
h.sort.to_h
h.sort{|a,z|a<=>z}.to_h
(перевірено 2.1.10, 2.3.3)
a
це масив, а не лише ключ). Я видалив свій коментар.
h.map(&:sort).map(&:to_h)
.
Примітка: у Ruby> = 1.9.2 є хеш, що зберігає замовлення: ключі замовлення вставляються буде в порядку їх перерахування. Нижче поширюється на старіші версії або на зворотний сумісний код.
Немає поняття відсортованого хешу. Так що ні, те, що ви робите, не правильно.
Якщо ви хочете, щоб це було відсортовано для відображення, поверніть рядок:
"{" + h.sort.map{|k,v| "#{k.inspect}=>#{v.inspect}"}.join(", ") + "}"
або, якщо вам потрібні ключі в порядку:
h.keys.sort
або, якщо ви хочете отримати доступ до елементів у порядку:
h.sort.map do |key,value|
# keys will arrive in order to this block, with their associated value.
end
але підсумовуючи, немає сенсу говорити про відсортований хеш. У документах "Порядок, в якому ви переходите хеш або за ключем, або за значенням, може здатися довільним, і, як правило, не буде в порядку вставки". Тому вставлення ключів у певному порядку в хеш не допоможе.
Я завжди користувався sort_by
. Вам потрібно обернути #sort_by
вихід, Hash[]
щоб він вивів хеш, інакше він виводить масив масивів. Крім того, для цього ви можете запустити #to_h
метод на масиві кортежів, щоб перетворити їх у k=>v
структуру (хеш).
hsh ={"a" => 1000, "b" => 10, "c" => 200000}
Hash[hsh.sort_by{|k,v| v}] #or hsh.sort_by{|k,v| v}.to_h
У " Як сортувати Ruby Hash за значенням числа " є аналогічне запитання . ".
sort_by
на хеші поверне масив. Вам потрібно буде відобразити його знову як хеш. Hash[hsh.sort_by{|k,v| v}]
hsh.sort_by(&:last).to_h => {"b"=>10, "a"=>1000, "c"=>200000}
.
to_h
підтримуються лише в Ruby 2.1.0+
sort_by{|k,v| v}.to_h)
Ні, це не так (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)
Для великих хесів різниця виросте до 10 разів і більше
Ви дали найкращу відповідь собі в ОП: Hash[h.sort]
Якщо ви бажаєте отримати більше можливостей, ось на місці модифікація оригінального хешу, щоб зробити його сортованим:
h.keys.sort.each { |k| h[k] = h.delete k }
Сортуйте хеш за ключем , поверніть хеш у Ruby
З руйнуванням і сортом Hash #
hash.sort { |(ak, _), (bk, _)| ak <=> bk }.to_h
Численні # sort_by
hash.sort_by { |k, v| k }.to_h
Хеш # сортування з поведінкою за замовчуванням
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 }
Примітка: <Рубін 2.1
array = [["key", "value"]]
hash = Hash[array]
hash #=> {"key"=>"value"}
Примітка:> Ruby 2.1
[["key", "value"]].to_h #=> {"key"=>"value"}
v
ви не використовуєте, ви маєте префікс підкреслитиhash.sort_by { |k, _v| k }.to_h
ActiveSupport :: OrdersHash - це ще один варіант, якщо ви не хочете використовувати рубін 1.9.2 або прокручувати власні обхідні шляхи.
@ordered = {}
@unordered.keys.sort.each do |key|
@ordered[key] = @unordered[key]
end
У мене була така ж проблема (мені довелося сортувати обладнання за їх назвою), і я вирішив так:
<% @equipments.sort.each do |name, quantity| %>
...
<% end %>
@equipments - хеш, який я будую на своїй моделі і повертаю на свій контролер. Якщо ви зателефонуєте .sort, він буде сортувати хеш на основі його ключового значення.
Мені сподобалось рішення в попередньому пості.
Я зробив міні-клас, назвав його class AlphabeticalHash
. Вона також має метод , званий ap
, який приймає один аргумент, Hash
, в якості вхідних даних: ap variable
. Акін до п.п. ( pp variable
)
Але він (спробуйте і) надрукує в алфавітному списку (його клавіші). Не знаю, якщо хтось хоче скористатися цим, він доступний як дорогоцінний камінь, ви можете встановити його як такий:gem install alphabetical_hash
Для мене це досить просто. Якщо іншим потрібен додатковий функціонал, дайте мені знати, я включу його в дорогоцінний камінь.
EDIT: Кредит йде на Пітера , який дав мені ідею. :)
each
абоeach_pair
повторюєте його. Навіть тоді я б, мабуть, все-таки захоплював ключі, сортував їх, а потім перебирав їх, захоплюючи значення за потребою. Це гарантує, що код буде вести себе правильно на старих рубінах.