在 Ruby 中按布尔值对对象进行排序

Posted

技术标签:

【中文标题】在 Ruby 中按布尔值对对象进行排序【英文标题】:Sort Objects by Boolean values in Ruby 【发布时间】:2010-10-28 13:56:21 【问题描述】:

如果这个问题之前已经回答过或者很明显,我深表歉意...在这里和 Goog 上进行了一些搜索,但找不到答案。

我希望按价格对一组提供者进行排序,以及它们是否是首选提供者? (对或错)

例如在array p of Providers...

p1.price == 1, p1.preferred_provider? == false
p2.price == 2, p2.preferred_provider? == true
p2.price == 3, p3.preferred_provider? == true

我想 p.sort_by 并得到:

[p2 p3 p1]

内测

p.sort_by |x| x.preferred_provider?, x.price 

不起作用并得到...

undefined method `<=>' for false:FalseClass

对解决此问题的更好方法有什么建议吗?

【问题讨论】:

实际上,您几乎拥有它:p.sort_by |x| [x.preferred_provider? ? 0 : 1, x.price] . 啊...很好。重构候选人。谢谢。 【参考方案1】:

大多数语言都提供了接受comparators 处理这类事情的排序函数。在 Ruby 中,这只是 array.sort:

p.sort |a, b| if (a.preferred_provider? == b.preferred_provider?
               then a.price <=> b.price
               elsif a.preferred_provider?
                    1
               else -1
       

【讨论】:

这个逻辑没有返回正确的顺序,但它使用 a.preferred_provider 让我走上了正确的道路? == b.preferred_provider?并反转 1 和 -1。谢谢 糟糕,您当然想在此处使用 ==(现已修复)。更详细地说,如果 a 在 b 之后,闭包应该返回一个正数,如果 a 在 b 之前,则返回一个负数,如果它们相等,则返回 0 用于排序目的。这样,对数值进行排序的简单实现是 |a,b| a - b。【参考方案2】:

您可以在Provider 类上定义一个&lt;=&gt; 来做您想做的事情,然后使用Array.sort 方法(而不是Enumerable.sort_by)进行排序。这是我整理的&lt;=&gt; 的定义:

class Provider
  def <=>(other)
    if preferred_provider?
      if other.preferred_provider?
        @price <=> other.price
      else
        1
      end
    else
      if other.preferred_provider?
        -1
      else
        @price <=> other.price
      end
    end
  end
end

那么,如果你有你的数组p,你可以做p_sorted = p.sort

(请注意,我没有测试过这段代码,所以可能会有一些错误,但我认为它可以证明这个想法。)

【讨论】:

这可行,但由于我在原始问题中没有说明的原因,其他解决方案更适合我的问题。谢谢...非常感谢。

以上是关于在 Ruby 中按布尔值对对象进行排序的主要内容,如果未能解决你的问题,请参考以下文章

在Java中按属性值对对象ArrayList进行排序

在javascript中按子数组属性值对对象数组进行排序

Ruby 按布尔值和数字排序

在视图中按布尔值过滤 Foreach

在Python中按值对嵌套字典进行排序,并按另一个值对余数进行排序

Python Bool 和 int 比较以及使用布尔值对列表进行索引