在Ruby中重新排序哈希表。让一个键永远排在最后。

6

假设我有一个哈希表:

h = {:a=>1, :b=>3, :c=>2, :d=>4}

我希望根据键对其进行排序,但我希望:c始终排在最后。我真的不关心其他项目的顺序,只要:c作为最后一个即可...
有简单的方法吗?
我的想法是获取所有键,删除:c,对它们进行排序并放入新数组中,然后将:c推入该数组?
2个回答

15

如果您不关心除“c”之外的顺序,那么我会使用:

hash[:c] = hash.delete(:c)

例如:

hash = {:d=>4, :c=>2, :b=>3, :a=>1, }
hash # => {:d=>4, :c=>2, :b=>3, :a=>1}

hash[:c] = hash.delete(:c)
hash # => {:d=>4, :b=>3, :a=>1, :c=>2}

在添加哈希表内容时,请不要浪费时间或 CPU,每次添加完成后再进行排序。仅在需要从哈希表中读取值之前进行排序。


我不明白为什么删除操作会将 :c 移动到数组的末尾

根据哈希表的文档:

哈希表按照相应键插入的顺序枚举它们的值。

Ruby 保持哈希表插入顺序。与某些人所说的相反,它们并没有被排序。当我们删除键时,Ruby会返回其相应的值,然后将该值立即分配回哈希表中的 :c 键。由于它是最后添加的,因此它将位于哈希表的末尾。


它的返回哈希值为{:b => 3, :c => { :c => 2}}。 - Joel Grannas
你的 Ruby 版本是多少?低于 1.9 吗?它在当前/支持的 Ruby 版本上可以正常工作。 - the Tin Man
这些样例是使用Ruby v2.1制作的,并在1.9.3-p484上在PRY和IRB中进行了测试。 - the Tin Man
是的,我犯了一个简单的错误,返回了hash[:c]而不是只返回hash。谢谢您先生 :) - Joel Grannas
我喜欢看到完美的答案。Joel:如果你想要它第一:hash = {:c=>hash[:c]}.merge(hash) - Cary Swoveland

1

你的方法可行,以下方法也同样可行:

Hash[h.sort_by {|k, v| k == :c ? 1 : 0}]

以及其他几种方法。:-)


2
这很有可能改变那些不是:c的键的顺序,因为#sort_by不是稳定的。 - Ja͢ck

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接