Будет ли это лучший способ отсортировать хэш и вернуть объект 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
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 по числовому значению? ».
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.sort { |(ak, _), (bk, _)| ak <=> bk }.to_h
Перечислимых # sort_by
hash.sort_by { |k, v| k }.to_h
Hash # sort с поведением по умолчанию
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 }
Примечание: <Ruby 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 :: 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
, который принимает один аргумент, Hash
, в качестве входных данных: ap variable
. Сродни пп ( pp variable
)
Но он будет (пытаться и) печатать в алфавитном списке (его ключи). Не знаю, если кто-то еще хочет использовать это, он доступен как драгоценный камень, вы можете установить его так:gem install alphabetical_hash
Для меня это достаточно просто. Если другим понадобится больше функциональности, дайте мне знать, я включу их в жемчужину.
РЕДАКТИРОВАТЬ: Кредит идет на Питера , который дал мне идею. :)
each
или не выполняетеeach_pair
его итерацию. Даже тогда я, вероятно, все еще собираю ключи, сортирую их, а затем перебираю их, получая значения по мере необходимости. Это гарантирует, что код будет работать правильно на старых Ruby.