如何在Ruby中按值和键对哈希进行排序?例如
h = {4 => 5, 2 => 5, 7 => 1}
会按照顺序排列
[[7, 1], [2,5], [4, 5]]
我可以通过执行以下操作来按值排序
h.sort {|x,y| x[1] <=> y[1]}
但是如果值相同,我无法想出如何基于值和键进行排序。
h.sort_by {|k, v| [v, k] }
这个方法利用了Array
混入Comparable
并逐个元素地定义了<=>
。
需要注意的是,上面的代码等效于:
h.sort_by {|el| el.reverse }
等价于
h.sort_by(&:reverse)
可能更易读,也可能不是。
如果你知道哈希表通常是先按键排序,然后按值排序,那么上面的内容就很明显了。也许可以写一个简短的注释:
h.sort_by(&:reverse) # sort by value first, then by key
注意:如果你只是想委托给某个属性的 `<=>` 方法(即按照键排序而不是一般比较函数),通常最好使用 `sort_by` 而不是 `sort`。它更容易阅读。一般来说,它也更快,但可读性方面更为重要。h.sort_by {|el| el[1] }
个人而言,我更喜欢在块参数列表中使用解构绑定,而不是使用 el[0]
和 el[1]
:
h.sort_by {|key, value| value }
然而,在这种特殊情况下,el[1]
也恰好与el.last
相同,
因此您可以简单地写成:
h.sort_by(&:last)
each
方法实现sort
和sort_by
。哈希的each
方法生成[k,v]数组,块中的|k,v|
因此相当于k,v=[kx,vx]
并行赋值。正如Jörg的|el|
示例所示,您可以在那里使用单个变量并获得行为el=[kx,vx]
。至于这件事,您可以做|a,b,c,d,e|
并获得a,b,c,d,e=[kx,vx]
,尽管显然这不会很有用。 - glenn mcdonalddef foo; yield 1; yield 1, 2; yield 1, 2, 3 end; puts '1 param'; foo {|a| p a }; puts '2 params'; foo {|a, b| p a, b }; puts '3 params'; foo {|a, b, c| p a, b, c }
。简而言之:块参数语义比方法参数语义宽松得多。它们的行为更像多重赋值。(事实上,在 Ruby 1.9 之前,块确实使用赋值,这意味着您可以做一些非常疯狂的事情,比如foo {|@bar, baz.quux|}
,它会将传递到块中的值分配给实例变量@bar
并调用 setterbaz.quux=
。) - Jörg W Mittag