11

假设我有以下数组:

arr = [[5, 1], [2, 7]]

我想找到最小元素,比较元素的第二个元素。最小元素将是[5, 1]因为1小于7。我可以使用以下代码:

arr.min {|a,b| a[1] <=> b[1]}

为了计算最大值,我可以这样做:

arr.max {|a,b| a[1] <=> b[1]}

这给了[2, 7].

我一直使用同一个块。我想把那个块放在某个地方并将它提供给 min/max 函数。我希望是这样的:

blo = lambda {|a,b| a[1] <=> b[1]}
arr.min blo

会工作,但它没有。关于我如何做到这一点的任何想法?

4

5 回答 5

24

使用&运算符将Proc​​对象变成块。

arr.min &blo
于 2010-10-18T15:21:25.123 回答
14

@sepp2k 的答案是更一般的答案,但在您的具体情况下,我会使用

arr.min_by(&:last)
arr.max_by(&:last)

因为这比所有那些花括号和方括号以及浮动的数组索引要明显得多

于 2010-10-18T16:02:59.033 回答
3

如果您只需要最小值和最大值,则可以使用Enumerable#minmax方法并同时计算两者:

min, max = arr.minmax {|a,b| a[1] <=> b[1]}
#=> [[5, 1], [2, 7]]
min
#=> [5, 1]
max
#=> [2, 7]

编辑:见鬼,我刚刚注意到还有minmax_by,所以你可以将它与last方法结合起来,并有:

min, max = arr.minmax_by &:last
于 2010-10-18T18:00:48.520 回答
2

这个怎么样?

=> [[5, 4], [9, 5], [2, 7]]
>> arr.sort!{|x,y| x[1]<=>y[1] }
=> [[5, 4], [9, 5], [2, 7]]
>> min,max=arr[0],arr[-1]
=> [[5, 4], [2, 7]]
于 2010-10-18T15:26:00.837 回答
2

解决此类问题的一个更通用的解决方案是完全避免嵌套数组并使用类来代替。然后,您可以为该类定义 <=> 运算符,让您可以访问 Comparable mixin (http://ruby-doc.org/core/classes/Comparable.html) 中的所有函数,为您提供 <, <= 、==、>= 和 > 运算符和方法 'between?'

这只是一个示例,在现实生活中,您将使用描述它们存储内容的类:

class Duo

  include Comparable

  def initialize( a, b )
      @a = a
      @b = b
  end

  def <=>(rhs)
      @b <=> rhs.b
  end

end

如果您有一个 Duo 对象数组,则可以使用 min、max 和 sort 函数,而无需定义比较运算符。所以...

@a = Duo.new( 1, 10 )
@b = Duo.new( 2, 5 )
@c = Duo.new( 3, 1 )

[ @a, @b, @c ].sort

将返回数组 [ @c, @b, @a ]

[@a, @b, @c].max

会回来@a

这更像是“Ruby 方式”,而不是嵌套数据结构,其逻辑依赖于数组中的位置。一开始需要做更多的工作,但从长远来看,你会发现它会好得多

Ruby 是一种非常面向对象的编程语言,并提供了非常强大的工具供您使用。我强烈建议您阅读诸如“The Ruby Programming Language”或“The Ruby Way”之类的书,以正确了解该语言的强大功能。

于 2010-10-18T17:52:21.223 回答