我正在尝试按字母顺序对哈希进行排序,但似乎没有找到不创建自己的排序类就能完成的方法。我找到了下面的代码可以按值对整数进行排序,我试图对其进行修改,但没有成功。
temp["ninjas"]=36
temp["pirates"]=12
temp["cheese"]=222
temp.sort_by { |key, val| key }
我的目标是按键对哈希进行排序,然后输出值。我将不得不多次使用不同的哈希顺序但相同的值来完成此操作。
我正在尝试按字母顺序对哈希进行排序,但似乎没有找到不创建自己的排序类就能完成的方法。我找到了下面的代码可以按值对整数进行排序,我试图对其进行修改,但没有成功。
temp["ninjas"]=36
temp["pirates"]=12
temp["cheese"]=222
temp.sort_by { |key, val| key }
我的目标是按键对哈希进行排序,然后输出值。我将不得不多次使用不同的哈希顺序但相同的值来完成此操作。
Ruby的 `Hash` 有一个构造函数可以使用此输出。
请尝试以下内容:
temp = Hash[ temp.sort_by { |key, val| key } ]
更简洁地说
temp = temp.sort_by { |key| key }.to_h
如果您的哈希表中包含混合键类型,这将无法正常工作(例如Ruby不会自动区分String
和Symbol
),您将收到类似于comparison of Symbol with String failed (ArgumentError)的错误消息。如果是这样,您可以将上述内容修改为:temp = Hash[ temp.sort_by { |key, val| key.to_s } ]
解决这个问题的一个方法是使用 to_s
方法将键转换为字符串。但需要注意的是,键仍将保留其原始类型,这可能会导致后续代码中的假设出现问题。此外,大多数内置类都支持 .to_s
方法,因此您可能会从中获得不想要的结果(例如数字键的意外排序顺序或其他意外的类型)。
此外,您可以像这样将键转换为 Strings
:
temp = Hash[ temp.map { |key, val| [key.to_s, val] }.sort ]
然而,采用这种方法会丢失有关原始密钥类型的信息,从而无法可靠地引用回原始数据。
temp = Hash[ temp.sort_by { |key, val| key.to_s } ]
来解决这个问题,但要小心,这会将符号键更改为字符串...如果你真的想按排序顺序处理数据,你需要决定一个数据类型作为你的键,并坚持使用它。 - Neil Slatersort_by
不会改变键,它只是使用块中的值进行排序。传递给 Hash[]
构造函数的参数具有与原始哈希相同的键。 - Kazim Zaidisorted_by_key = Hash[original_hash.sort]
通过按键的字母顺序将original_hash
的键/值插入,将创建一个新的哈希表。Ruby 2.x哈希表会记住它们的插入顺序,因此如果你枚举它或输出它,这个新的哈希表将按键排序后显示。
如果您以非字母顺序插入更多的元素,则当然无法保证这一点。
此外,这假设原始哈希表键都是可排序/可比较的。
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]
有些编程语言甚至不能对哈希表进行排序,仅通过已排序的键列表访问它是提取元素按顺序的唯一方式,因此最好不要养成依赖键值对顺序的习惯,而是依赖键。
Hash#sort_by
,然后是普通的 Hash#each
。不确定是否有更“Ruby”的方法来处理这种情况...您有什么建议吗? - pjvleeuwenHash#invert
是按值排序的起点。将结果分配给一个新变量。添加 keys
和 sort
,你就快成功了。https://dev59.com/5mgu5IYBdhLWcg3w6bGo - the Tin ManHash#sort_by
方法(当在块中输出可比较值时,这种方法很简洁)...irb(main):001:0> h = { a: 0, b: 5, c: 3, d: 2, e: 3, f:1 }
=> {:a=>0, :b=>5, :c=>3, :d=>2, :e=>3, :f=>1}
irb(main):002:0> h.sort_by { |pair| pair[1] }.to_h
=> {:a=>0, :f=>1, :d=>2, :c=>3, :e=>3, :b=>5}
...或反向变体...
irb(main):003:0> h.sort_by { |pair| pair[1] }.reverse.to_h
=> {:b=>5, :e=>3, :c=>3, :d=>2, :f=>1, :a=>0}
除此之外,还有一种选项是使用 Array#sort
方法,它允许您定义自己的比较规则(例如,按值升序排序,但对于相等的值,则按键降序排序):
irb(main):004:0> h.to_a.sort { |one, other| (one[1] == other[1]) ? other[0] <=> one[0] : one[1] <=> other[1] }.to_h
=> {:a=>0, :f=>1, :d=>2, :e=>3, :c=>3, :b=>5}
这最后一种选择不太简洁,但可以更灵活(例如自定义逻辑来处理混合类型)。
您可以创建一个新的空哈希表来保存排序后的哈希数据。遍历返回的数组并将数据加载到新哈希表中以保存排序后的哈希数据。
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等于{"cheese"=>222, "ninjas"=>36, "pirates"=>12}