Сортировать хеш по ключу, вернуть хеш в Ruby - PullRequest
245 голосов
/ 02 декабря 2010

Будет ли это наилучшим способом сортировки хеша и возврата объекта хеша (вместо массива):

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}

Ответы [ 10 ]

203 голосов
/ 11 марта 2014

В Ruby 2.1 это просто:

h.sort.to_h
80 голосов
/ 02 декабря 2010

Примечание: 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

но в целом нет смысла говорить о отсортированном хэше. Из документов «Порядок, в котором вы пересекаете хеш по ключу или значению, может показаться произвольным и обычно не будет в порядке вставки». Поэтому вставка ключей в определенном порядке в хэш не поможет.

63 голосов
/ 28 января 2014

Я всегда использовал 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 по числовому значению? ".

13 голосов
/ 27 июня 2013

Нет, это не так (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х и более

12 голосов
/ 12 июня 2013

Вы дали лучший ответ себе в ОП: Hash[h.sort] Если вы жаждете большего количества возможностей, вот модификация исходного хэша на месте, чтобы сделать его отсортированным:

h.keys.sort.each { |k| h[k] = h.delete k }
6 голосов
/ 03 декабря 2010

ActiveSupport :: OrderedHash - это еще один вариант, если вы не хотите использовать ruby ​​1.9.2 или накатывать собственные обходные пути.

4 голосов
/ 17 апреля 2018

Сортировка хеша по ключу , возврат хеша в Ruby

С деструктуризацией и сортировкой Hash #

hash.sort { |(ak, _), (bk, _)| ak <=> bk }.to_h

Enumerable # 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 }

Примечание:

[["key", "value"]].to_h #=> {"key"=>"value"}
0 голосов
/ 31 июля 2017

У меня была такая же проблема (мне пришлось отсортировать оборудование по имени), и я решил так:

<% @equipments.sort.each do |name, quantity| %>
...
<% end %>

@ equipments - это хеш, который я строю на своей модели и возвращаю на свой контроллер. Если вы вызовете .sort, он будет сортировать хеш по значению ключа.

0 голосов
/ 11 октября 2013
@ordered = {}
@unordered.keys.sort.each do |key|
  @ordered[key] = @unordered[key]
end
0 голосов
/ 14 апреля 2012

Мне понравилось решение в предыдущем посте.

Я сделал мини-класс, назвал его class AlphabeticalHash. Он также имеет метод с именем ap, который принимает один аргумент Hash в качестве ввода: ap variable. Сродни пп (pp variable)

Но он будет (пытаться) печатать в алфавитном списке (его ключи). Не знаю, если кто-то еще хочет использовать это, он доступен как драгоценный камень, вы можете установить его так: gem install alphabetical_hash

Для меня это достаточно просто. Если другим нужно больше функциональности, пусть я знаю, я включу его в драгоценный камень.

РЕДАКТИРОВАТЬ: Кредит идет на Питер , который дал мне идею. :)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...