Будет ли это лучший способ сортировки хеша и вернуть объект Hash (вместо 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}
Будет ли это лучший способ сортировки хеша и вернуть объект Hash (вместо 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}
В Ruby 2.1 это просто:
h.sort.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
но в целом, нет смысла говорить о сортированном хеше. Из docs: "Порядок, в котором вы проходите хэш с помощью ключа или значения, может показаться произвольным и, как правило, не будет в порядке вставки". Поэтому вставка ключей в определенном порядке в хэш не поможет.
Я всегда использовал 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" по номеру?".
Нет, это не (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)
Для больших хэшей разница вырастет до 10x и более
Вы дали лучший ответ себе в OP: Hash[h.sort]
Если вы жаждете больше возможностей, здесь вы можете изменить исходный хэш на месте, чтобы он отсортировался:
h.keys.sort.each { |k| h[k] = h.delete k }
ActiveSupport:: OrderedHash - это еще один вариант, если вы не хотите использовать ruby 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
, который принимает один аргумент, a Hash
, как вход: ap variable
. Сродни pp (pp variable
)
Но он будет (попробуйте и) распечатать в алфавитном списке (его ключи). Dunno, если кто-то еще хочет использовать это, он доступен как драгоценный камень, вы можете установить его как таковой: gem install alphabetical_hash
Для меня это достаточно просто. Если другим нужна дополнительная функциональность, пусть я знаю, я включу его в камень.
EDIT: кредит отправляется Peter, который дал мне эту идею.:)