ruby – 是否可以根据单个对象对方法的响应对对象列表进行排序?

前端之家收集整理的这篇文章主要介绍了ruby – 是否可以根据单个对象对方法的响应对对象列表进行排序?前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
我想展示一个产品的画廊,其中包括出售和不出售的产品.只有我想要出售的产品出现在列表的前面,并且不出售的对象将显示在列表的末尾.

一个简单的方法可以让我完成这个工作就是做两个列表,然后合并它们(一个on_sale?对象列表和一个不是on_sale?对象的列表):

available_products = []
sold_products = []
@products.each do |product|
  if product.on_sale?
    available_products << product
  else
    sold_products << product
  end
end

. . .但是,对于我现有的应用程序的结构,这将需要过多的重构,因为我的代码很奇怪(我失去了我的分页,我宁愿不重构).如果有办法通过我的产品型号的方法on_sale对现有的对象列表进行排序会更容易吗?它返回一个布尔值.

是否可以通过现有的列表更加优雅地迭代,并通过rails中的真实或虚假值进行排序?我只是问,因为有这么多我不知道隐藏在这个框架/语言(ruby),我想知道他们的工作是否已经在我之前完成.

解决方法

当然.理想情况下,我们将使用 sort_by!做这样的事情:
@products.sort_by! {|product| product.on_sale?}

或者snazzier

@products.sort_by!(&:on_sale?)

但可悲的是,< =不适用于布尔值(参见Why doesn’t sort or the spaceship (flying saucer) operator (<=>) work on booleans in Ruby?),sort_by不适用于布尔值,因此我们需要使用这个技巧(谢谢rohit89!)

@products.sort_by! {|product| product.on_sale? ? 0 : 1}

如果您想获得优势,则排序方法会占用一个块,并且在该块内,您可以使用任何您喜欢的逻辑,包括类型转换和多个键.尝试这样的东西:

@products.sort! do |a,b|
  a_value = a.on_sale? ? 0 : 1
  b_value = b.on_sale? ? 0 : 1
  a_value <=> b_value
end

或这个:

@products.sort! do |a,b|
  b.on_sale?.to_s <=> a.on_sale?.to_s
end

(把b放在前面,因为你想要“真”值出现在“假”之前)

或者如果您有次要排序:

@products.sort! do |a,b|
  if a.on_sale? != b.on_sale?
    b.on_sale?.to_s <=> a.on_sale?.to_s
  else
    a.name <=> b.name
  end
end

请注意,sort返回一个新的集合,通常是一个更干净,更容易出错的解决方案,但是sort!修改原始集合的内容,这是您要求的.

猜你在找的Ruby相关文章