Сортировка сложного рубинового хэша работает нормально, но невозможно изменить, что я могу сделать?

У меня есть хеш в ruby ​​со сложной структурой, например:

something = {}
something[1488343493] = { :type => 'tag', :name => 'v1.2', :sha => 'a66fd116e454378794d24c41c193d385be37436f'}
something[1488288253] = { :type => 'pull', :number => '469', :sha => '190ed76e30a5fa7d357e8bfb78adfa687a673635', :title => "Consistent file uploads "}
something[1468674242] = { :type => 'tag', :name => 'v1.1', :sha => '2cf4549d0181ad1d60fbd3bbe132b599a14a8965'}
something[1488457772] = { :type => 'pull', :number => '476', :sha => '5f51fa23ea79bd9b89703cb93a5e38a0f0a338bb', :title => "Extract i18n strings in modals/* "}
something[1488288044] = { :type => 'pull', :number => '470', :sha => 'ab98ec3bf7cbe04f11a17d30ed07e5323b45d5df', :title => "Stop copy & clickthrough from list summaries "}

Это в основном содержит список тегов Github и объединенных запросов на выборку. Я могу легко разобраться с этим .sort:

something.sort.each do | key, value | # sorts perfectly fine
  p "#{key} #{value[:type]} #{value[:sha]}"
end

Но я не хочу отсортированный хеш, а перевернутый хеш. И я полностью озадачен, я не могу полностью изменить это, пытаясь .reverse это дает NoMethodError для хэша:

something.reverse.each do | key, value | # undefined method `reverse' for #<Hash:0x0> (NoMethodError)
  p "#{key} #{value[:type]} #{value[:sha]}"
end

Пытаясь reverse_each просто ничего не делает

something.reverse_each do | key, value | # does not reverse at all
  p "#{key} #{value[:type]} #{value[:sha]}"
end

То же самое относится и к преобразованию в массив и к обращению, вообще ничего не делает:

gnihtemos = something.to_a.reverse.to_h # does not reverse at all
gnihtemos.each do | key, value |
  p "#{key} #{value[:type]} #{value[:sha]}"
end

gnihtemos = Hash[something.to_a.reverse] # does not reverse at all
gnihtemos.each do | key, value |
  p "#{key} #{value[:type]} #{value[:sha]}"
end

У меня заканчиваются варианты. Я использую Ruby 2.4.0p0, Что еще я могу сделать, чтобы повернуть вспять something?

4 ответа

Решение

reverse меняет текущий порядок Это означает, что вы должны отсортировать сначала и вернуться на второй шаг:

something.sort.reverse.each { ... }

Или вам нужно явно указать Ruby, как сортировать:

something.sort_by { |commit_id, _| -commit_id }.each { ... }

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

reversed = {}
something.keys.reverse.each { |k| reversed[k] = something[k] }

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

something = {
  1488343493 => { :type => 'tag', :name => 'v1.2', :sha => 'a66fd116e454378794d24c41c193d385be37436f'},
  1488288253 => { :type => 'pull', :number => '469', :sha => '190ed76e30a5fa7d357e8bfb78adfa687a673635', :title => "Consistent file uploads "},
  1468674242 => { :type => 'tag', :name => 'v1.1', :sha => '2cf4549d0181ad1d60fbd3bbe132b599a14a8965'},
  1488457772 => { :type => 'pull', :number => '476', :sha => '5f51fa23ea79bd9b89703cb93a5e38a0f0a338bb', :title => "Extract i18n strings in modals/* "},
  1488288044 => { :type => 'pull', :number => '470', :sha => 'ab98ec3bf7cbe04f11a17d30ed07e5323b45d5df', :title => "Stop copy & clickthrough from list summaries "},
}

rev_sorted_keys = something.keys.sort.reverse
# => [1488457772, 1488343493, 1488288253, 1488288044, 1468674242]

something.values_at(*rev_sorted_keys)
# => [{:type=>"pull",
#      :number=>"476",
#      :sha=>"5f51fa23ea79bd9b89703cb93a5e38a0f0a338bb",
#      :title=>"Extract i18n strings in modals/* "},
#     {:type=>"tag",
#      :name=>"v1.2",
#      :sha=>"a66fd116e454378794d24c41c193d385be37436f"},
#     {:type=>"pull",
#      :number=>"469",
#      :sha=>"190ed76e30a5fa7d357e8bfb78adfa687a673635",
#      :title=>"Consistent file uploads "},
#     {:type=>"pull",
#      :number=>"470",
#      :sha=>"ab98ec3bf7cbe04f11a17d30ed07e5323b45d5df",
#      :title=>"Stop copy & clickthrough from list summaries "},
#     {:type=>"tag",
#      :name=>"v1.1",
#      :sha=>"2cf4549d0181ad1d60fbd3bbe132b599a14a8965"}]

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

Сортировка имеет гораздо больше смысла с массивом, который часто используется в качестве очереди или списка, где может быть важен порядок.

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

И это решение: .sort.reverse, как в:

something.sort.reverse.each do | key, value |
  p "#{key} #{value[:type]} #{value[:sha]}"
end
Другие вопросы по тегам