Я не уверен, что есть много преимуществ в сортировке хэша, если вы не используете eachили не выполняете each_pairего итерацию. Даже тогда я, вероятно, все еще собираю ключи, сортирую их, а затем перебираю их, получая значения по мере необходимости. Это гарантирует, что код будет работать правильно на старых Ruby.
Жестянщик
Имеет смысл и в ruby 1.9. У меня была коллекция встреч, сгруппированных по датам (в виде ключей) из базы данных, и я вручную перебрал рубин. Например. {"2012-09-22": [...], "2012-09-30": [...], "2012-10-12": [...]}
Adit Saxena
Да, я считаю, что ваш хэш-процесс [h.sort] более эффективен, чем сортировка ключей, а затем повторный доступ к хешу через отсортированные ключи.
@zachaysan, но это работает: h.sort{|a,z|a<=>z}.to_h(протестировано 2.1.10, 2.3.3)
whitehat101
@ whitehat101 Вы правы. У меня была ошибка ( aэто массив, а не только ключ). Я удалил свой комментарий.
zachaysan
Только в случае , если кто - то ищет способ сортировки массива хэшей, это будет делать трюк (где Н массив): h.map(&:sort).map(&:to_h).
JM Janzen
82
Примечание: Ruby> = 1.9.2 имеет хэш, сохраняющий порядок: ключи порядка вставляются в порядке их перечисления. Нижеследующее относится к более старым версиям или к обратно совместимому коду.
Не существует понятия отсортированного хэша. Так что нет, то, что вы делаете, не правильно.
Если вы хотите, чтобы он был отсортирован для отображения, верните строку:
или, если вы хотите получить доступ к элементам по порядку:
h.sort.map do|key,value|# keys will arrive in order to this block, with their associated value.end
но в целом нет смысла говорить о отсортированном хэше. Из документов : «Порядок, в котором вы пересекаете хеш по ключу или значению, может показаться произвольным и обычно не будет в порядке вставки». Поэтому вставка ключей в определенном порядке в хэш не поможет.
Повторяю мой первый комментарий (чувствуя себя смешно): Например, полагаясь на порядок хэшей, можно было бы молча и непредсказуемо сломаться для версий Ruby старше 1.9.2.
Джо Лисс
5
Как этот ответ получил около 20 + 1, не ответив ни на одну из двух частей вопроса ОП? «1) Будет ли это (пример OP) лучшим способом отсортировать хеш, 2) и вернуть объект Hash»? Я не завидую +1: просто после прочтения ответа у меня все еще остаются оригинальные вопросы. Также, если дело в том, что нет такой вещи, как отсортированный хэш, посмотрите на комментарии для выбранного ответа на этот вопрос stackoverflow.com/questions/489139/…
jj_
64
Я всегда использовал sort_by. Вам нужно обернуть #sort_byвывод, Hash[]чтобы он выводил хеш, иначе он выводит массив массивов. В качестве альтернативы, для этого вы можете запустить #to_hметод на массиве кортежей, чтобы преобразовать их в k=>vструктуру (хеш).
использование sort_byхэша вернет массив. Вы должны будете отобразить это как хэш снова. Hash[hsh.sort_by{|k,v| v}]
Stevenspiel
1
да, класс перечислителя интерпретирует хэши как массивы, как мне кажется
boulder_ruby
3
Правильно, сортировка по значениям: hsh.sort_by(&:last).to_h => {"b"=>10, "a"=>1000, "c"=>200000}.
Кэри Свовеланд
1
Обратите внимание, что вызов to_hподдерживается только в Ruby 2.1.0+
Phrogz
1
в комментарии есть опечатка, исправление:sort_by{|k,v| v}.to_h)
джиттер
13
Нет, это не так (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 doHash[h.sort]endend
GC.start
b.report("keys sort")do
many.times do
nh ={}
h.keys.sort.each do|k|
nh[k]= h[k]endendendend
user system total real
hash sort 0.4000000.0000000.400000(0.405588)
keys sort 0.2500000.0100000.260000(0.260303)
Я исправил ссылку, указывающую на Google, на случай, если какой-нибудь историк захочет исследовать, как это могло быть сделано в прошлом. Но любой, кто придет к этому сейчас, должен использовать более свежую версию Ruby.
Я сделал мини-класс, назвал это class AlphabeticalHash. Она также имеет метод , называемый ap, который принимает один аргумент, Hash, в качестве входных данных: ap variable. Сродни пп ( pp variable)
Но он будет (пытаться и) печатать в алфавитном списке (его ключи). Не знаю, если кто-то еще хочет использовать это, он доступен как драгоценный камень, вы можете установить его так:gem install alphabetical_hash
Для меня это достаточно просто. Если другим понадобится больше функциональности, дайте мне знать, я включу их в жемчужину.
РЕДАКТИРОВАТЬ: Кредит идет на Питера , который дал мне идею. :)
each
или не выполняетеeach_pair
его итерацию. Даже тогда я, вероятно, все еще собираю ключи, сортирую их, а затем перебираю их, получая значения по мере необходимости. Это гарантирует, что код будет работать правильно на старых Ruby.Ответы:
В Ruby 2.1 это просто:
источник
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 имеет хэш, сохраняющий порядок: ключи порядка вставляются в порядке их перечисления. Нижеследующее относится к более старым версиям или к обратно совместимому коду.
Не существует понятия отсортированного хэша. Так что нет, то, что вы делаете, не правильно.
Если вы хотите, чтобы он был отсортирован для отображения, верните строку:
или, если вы хотите, чтобы ключи были в порядке:
или, если вы хотите получить доступ к элементам по порядку:
но в целом нет смысла говорить о отсортированном хэше. Из документов : «Порядок, в котором вы пересекаете хеш по ключу или значению, может показаться произвольным и обычно не будет в порядке вставки». Поэтому вставка ключей в определенном порядке в хэш не поможет.
источник
Я всегда использовал
sort_by
. Вам нужно обернуть#sort_by
вывод,Hash[]
чтобы он выводил хеш, иначе он выводит массив массивов. В качестве альтернативы, для этого вы можете запустить#to_h
метод на массиве кортежей, чтобы преобразовать их вk=>v
структуру (хеш).Аналогичный вопрос есть в разделе « Как отсортировать хэш 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)
Для больших хешей разница вырастет до 10х и более
источник
Вы дали лучший ответ себе в ОП:
Hash[h.sort]
Если вы стремитесь к большему количеству возможностей, вот модификация исходного хеша для его сортировки:источник
С деструктуризацией и хэш-сортировкой
Перечислимых # sort_by
Hash # sort с поведением по умолчанию
Примечание: <Ruby 2.1
Примечание:> Ruby 2.1
источник
v
вы должны префикс подчеркиванияhash.sort_by { |k, _v| k }.to_h
ActiveSupport :: OrderedHash - это еще один вариант, если вы не хотите использовать ruby 1.9.2 или откатить собственные обходные пути.
источник
источник
У меня была такая же проблема (мне пришлось отсортировать оборудование по имени), и я решил так:
@equipments - это хеш, который я строю на своей модели и возвращаю на свой контроллер. Если вы вызываете .sort, он сортирует хеш по значению ключа.
источник
Мне понравилось решение в предыдущем посте.
Я сделал мини-класс, назвал это
class AlphabeticalHash
. Она также имеет метод , называемыйap
, который принимает один аргумент,Hash
, в качестве входных данных:ap variable
. Сродни пп (pp variable
)Но он будет (пытаться и) печатать в алфавитном списке (его ключи). Не знаю, если кто-то еще хочет использовать это, он доступен как драгоценный камень, вы можете установить его так:
gem install alphabetical_hash
Для меня это достаточно просто. Если другим понадобится больше функциональности, дайте мне знать, я включу их в жемчужину.
РЕДАКТИРОВАТЬ: Кредит идет на Питера , который дал мне идею. :)
источник