在对数组进行排序时是否有避免这种错误的方法?
ArgumentError: comparison of Hash with Hash failed
我正在寻找这样的东西:
a.sort if a.is_sortable?
答案 0 :(得分:4)
排序通常基于Comparable
:
Comparable
混合用于其对象可以排序的类。该类必须定义<=>
运算符,该运算符将接收方与另一个对象进行比较,并根据接收方是小于,等于还是大于另一个对象返回-1、0或+1。>
所以你可以看看:
a.grep(Comparable)
,查看其长度是否与a
相同。或者你可以说:
a.all? { |e| e.is_a? Comparable }
但是您实际上并不需要Comparable
来使#sort
正常工作,您只需要一个<=>
方法就可以说:
a.all? { |e| e.respond_to? :<=> }
当然,以上所有条件均假设a
的所有元素都与<=>
相同(即x <=> y
适用于任何两个条目x
和y
中的a
),即使a
的所有元素都是Comparable
或即使它们都对<=>
做出响应,也不一定是这种情况。我们还假设<=>
的实现是正确的,但是如果您对飞船运算符的实现不正确,那么所有的赌注都不会生效。
对于任意数组a
,判断是否可以对其进行排序的唯一方法是尝试对其进行排序并查看其是否爆炸。对于您对元素了解更多的数组(即,元素都是同一类的所有实例),您可以使用一些选择。
答案 1 :(得分:1)
简短的回答:不,没有is_sortable?
方法。
长答案:sort
使用<=>
运算符,因此您可以检查其是否已定义:
a.sort if a.all? { |item| item.respond_to?(:<=>) }
但是它是为哈希定义的,因为它们继承自Kernel
:
{}.respond_to?(:<=>) # => true
{}.method(:<=>) # => #<Method: Hash(Kernel)#<=>>
但是,当您尝试在散列上使用它时,通常会返回nil
,这会导致异常:
# No idea why this should work:
{} <=> {} # => 0
{a: :b} <=> {c: :d} # => nil
因此,如果最好使用sort_by
并提出自己的可以处理哈希的排序算法,则可能是最好的选择。