对复杂的 ruby 哈希进行排序可以正常工作,但无法逆转,我该怎么办?

Sorting a complex ruby hash works fine, but it's impossible to reverse, what can I do?

我在 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

同样适用于 converting to array and reversing,什么都不做:

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?

reverse 反转当前顺序。这意味着你必须先排序,然后在第二步反转:

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

或者您需要明确告诉Ruby如何排序:

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

好吧,有时只需要花时间在 Whosebug 上写下整个问题。我刚刚了解到 .reverse_each 实际上按照它所说的进行操作: 反转 哈希。我期待它 反向排序 哈希。

这是解决方案:.sort.reverse,如:

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

我不确定我是否理解你的问题。如果你想要的是你的散列在键的顺序被颠倒的意义上被颠倒,你可以这样做:

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 以与键相同的顺序提取值。

使用数组进行排序更有意义,数组通常用作顺序可能很重要的队列或列表。