Подтвердить что ты не робот

Как отсортировать Ruby Hash по алфавиту с помощью клавиш

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

temp["ninjas"]=36
temp["pirates"]=12
temp["cheese"]=222
temp.sort_by { |key, val| key }

Моя цель - заказать хеш-ключ, затем вывести значения. Мне придется делать это несколько раз с разными хэш-ордерами, но с теми же значениями.

4b9b3361

Ответ 1

Предполагая, что вы хотите, чтобы вывод был хешем, который будет перебирать ключи в отсортированном порядке, то вы почти на месте. Hash#sort_by возвращает Array of Array s, и все внутренние массивы являются двумя элементами.

В Ruby Hash есть конструктор, который может использовать этот вывод.

Попробуй это:

temp = Hash[ temp.sort_by { |key, val| key } ]

или более кратко

temp = temp.sort_by { |key| key }.to_h

Если ваш хэш имеет смешанные типы ключей, это не сработает (например, Ruby не будет автоматически сортировать String и Symbol по символам), и вы получите сообщение об ошибке, например, сравнение символа с строкой не удалось (ArgumentError). Если это так, вы можете изменить выше

temp = Hash[ temp.sort_by { |key, val| key.to_s } ] 

обойти проблему. Однако следует помнить, что ключи по-прежнему сохраняют свои первоначальные типы, что может вызвать проблемы с допущениями в последующем коде. Кроме того, большинство встроенных классов поддерживают метод .to_s, поэтому вы можете получить нежелательные результаты (например, неожиданный порядок сортировки для цифровых клавиш или другие непредвиденные типы).

Кроме того, вы можете преобразовать ключи в Strings следующим образом:

temp = Hash[ temp.map { |key, val| [key.to_s, val] }.sort ] 

, , хотя такой подход может привести к потере информации о типе исходного ключа, что делает невозможным надежное возвращение к исходным данным.

Ответ 2

sorted_by_key = Hash[original_hash.sort]

создаст новый хэш, вставив ключ/значения original_hash в алфавитном порядке по клавише. Хеши Ruby 2.x запоминают порядок их вставки, поэтому этот новый хеш будет отображаться отсортированным по ключу, если вы его перечислите или выведете.

Если вы вставляете больше элементов в не-алфавитном порядке, это, конечно, не будет выполнено.

Кроме того, это предполагает, что исходные хэш-ключи являются все сортируемыми/сопоставимыми.

Ответ 3

Ruby Hash помнит свой порядок вставки сейчас, но ранее Rubies < v1.9 нет. Но, не утруждайте себя сортировкой хэша, поскольку нет никакого преимущества для этого, потому что в основном Хэш представляет собой структуру с произвольным доступом. Это означает, что все элементы доступны в любое время, и не будет иметь значения, является ли первый или последний, вы можете получить к нему доступ точно так же.

В отличие от массива, который действует как последовательный/текстовый файл или цепочка или очередь, и вам приходится обращаться к нему линейно, итерируя его, что в этот момент порядок элементов имеет большое значение.

Итак, с помощью Hash, получить ключи, отсортировать их и либо перебрать по списку ключей, либо использовать values_at для извлечения всех значений одновременно. Например:

hash = {
    'z' => 9,
    'a' => 1
}

sorted_keys = hash.keys.sort # => ["a", "z"]
sorted_keys.each do |k|
  puts hash[k]
end
# >> 1
# >> 9

hash.values_at(*sorted_keys) # => [1, 9]

Некоторые языки даже не позволяют сортировать хэш, а доступ к нему через отсортированный список ключей - единственный способ извлечь элементы в порядке, поэтому, вероятно, неплохо не привыкать полагаться на по порядку пар ключ/значение, а вместо этого полагаться на клавиши.

Ответ 4

Вы можете создать новый пустой хеш для хранения отсортированных хэш-данных. Перейдите через возвращаемый массив и загрузите данные в новый хеш для хранения отсортированных хэш-данных.

temp = {}
temp["ninjas"]=36
temp["pirates"]=12
temp["cheese"]=222 
temp = temp.sort_by { |key, val| key }

temp_sorted = {}
temp.each { |sub_arr| temp_sorted[sub_arr[0]] = sub_arr[1] } 
temp = temp_sorted

temp теперь равно { "сыр" = > 222, "ниндзя" = > 36, "пираты" = > 12}