我希望展示products
的图库,其中包含既可以出售又可以出售的产品。只有我希望待售的products
出现在列表的前面,而非待售的对象才会出现在列表的末尾。
我完成此任务的一个简单方法是创建两个列表,然后合并它们(一个on_sale?对象列表和一个not on_sale?对象列表):
available_products = []
sold_products = []
@products.each do |product|
if product.on_sale?
available_products << product
else
sold_products << product
end
end
。 。 。但是对于我现有应用程序的结构,由于我的代码奇怪,这需要过多的重构(我失去了我的分页,我宁愿不重构)。如果有一种方法可以通过我的product
模型的方法on_sale?
对现有的对象列表进行排序,这将返回一个布尔值。
是否有可能更优雅地遍历现有列表并通过rails中的true或false值对其进行排序?我只是问,因为有很多我不知道隐藏在这个中框架/语言(ruby),我想知道他们是否在我之前完成了工作。
答案 0 :(得分:14)
不确定。理想情况下,我们会使用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}
如果你想变得更加漂亮,sort
方法需要一个块,在那个块中你可以使用你喜欢的任何逻辑,包括类型转换和多个键。尝试这样的事情:
@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放在a之前,因为您希望"true"
之前的值"false"
}
或者如果您有二级分类:
@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!
会修改原始集合的内容,您认为这是一个要求。
答案 1 :(得分:4)
@products.sort_by {|product| product.on_sale? ? 0 : 1}
当我不得不根据布尔值进行排序时,这就是我所做的。
答案 2 :(得分:4)
无需排序:
products_grouped = @products.partition(&:on_sale?).flatten(1)
答案 3 :(得分:0)
升序和降序可以通过互换来改变&#34; false&#34;和&#34;真&#34;
Products.sort_by {|product| product.on_sale? == true ? "false" : "true" }