简体   繁体   English

如何按升序对ruby数组进行排序,但最后保持为零

[英]How to sort a ruby array in ascending order but keep zero last

I am trying to sort a Ruby array with the following function 我试图用以下函数对Ruby数组进行排序

@prices = @item.prices.sort { |x,y| x.total <=> y.total }

Which orders from the lowest to the highest cost. 哪个订单从最低到最高成本。 However some products have a total of 0.00 and I want them to appear last rather than at the top. 然而,有些产品总共有0.00,我希望它们出现在最后而不是顶部。

I have tried a few things but would like some way to modify this block to sort zero at the bottom but keep the rest in ascending order. 我已经尝试了一些东西但是想要某种方法来修改这个块以在底部排序零但保持其余的按升序排列。

Thanks. 谢谢。

试试这个,我认为它正在按你的要求做:

@prices = @item.prices.sort {|a,b| a.total==0 ? 1 : b.total==0 ? -1 : a.total<=>b.total}
prices = [0, 1, 2, 0,4, 3]
prices = prices.sort_by do |price|
  [
    if price == 0
      1
    else
      0
    end,
    price
  ]
end
p prices
# => [1, 2, 3, 4, 0, 0]

The trick here is that arrays are compared by comparing their first elements, but if those elements are equal, then by comparing their next elements, and so on. 这里的技巧是通过比较它们的第一个元素来比较数组,但如果这些元素相等,那么通过比较它们的下一个元素,依此类推。 So having the sort_by block yield an array lets you determine primary sort order, secondary sort order, and so on in a clean manner. 因此,让sort_by块生成一个数组可以让您以干净的方式确定主排序顺序,二级排序顺序等。

Just for the record: 仅供记录:

>> a = [0, 1, 3, 0, 2, 5, 0, 9]
=> [0, 1, 3, 0, 2, 5, 0, 9]
>> a.sort_by { |x| x.zero? ? Float::MAX : x }
=> [1, 2, 3, 5, 9, 0, 0, 0]

On most platforms 1.0/0 will evaluate to Infinity , so you can also use this instead of Float::MAX : 在大多数平台上, 1.0/0将评估为Infinity ,因此您也可以使用它而不是Float::MAX

>> b = [1,4,2,0,5,0]
=> [1, 4, 2, 0, 5, 0]
>> Inf = 1.0/0
=> Infinity
>> b.sort_by { |x| x.zero? ? Inf : x }
=> [1, 2, 4, 5, 0, 0]

So devise a comparator to do that ... 所以设计一个比较器来做到这一点......

if x.total == 0
  # always consider 0 "largest" and no 0 can be larger than another
  # (make sure 0.0 is 0 and not a number really close to 0)
  # perhaps x or y should be first for other reasons as well?
  1
else
  # otherwise lower to higher as normal
  x.total <=> y.total
end

Or without comments: 或者没有评论:

foo.sort {|x, y| if x.total == 0 then 1 else x.total <=> y.total end}

Happy coding. 快乐的编码。

This would feel less hacky and less write-only to me: 对我来说,这会让我觉得不那么苛刻,也不那么只写:

prices = prices.sort_by do |price| 
  zero_status = price.zero? ? 1 : 0
  [zero_status, price]
end

because it's an idiomatic way of sorting something by two criteria, which is what you're doing here. 因为这是按照两个标准对事物进行排序的惯用方法,这就是你在这里做的事情。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM