Предоставить proc методу в виде блока

предположим, у меня есть следующий массив:

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

будет работать, но это не так. Есть идеи, как я могу это сделать?

5 ответов


использовать & оператор в свою очередь Proc объект в блок.

arr.min &blo

@sepp2k является более общим, но в вашем конкретном случае, я бы просто использовать

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

С много более очевидно, чем все эти фигурные скобки и квадратные скобки и индексы массива, плавающие вокруг.


если все, что вам нужно, это минимум и максимум, вы могли бы использовать Enumerable#minmax метод и вычислить оба сразу:

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

Edit: Черт, я только что заметил, что есть также minmax_by, Так что вы можете сочетать его с last способ и есть:

min, max = arr.minmax_by &:last

Как насчет этого?

=> [[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]]

более общее решение таких проблем-полностью избегать вложенных массивов и вместо этого использовать класс. Затем вы можете определить оператор для этого класса, предоставляя вам доступ ко всем функциям в сопоставимом mixin (http://ruby-doc.org/core/classes/Comparable.html) дает вам =, и > операторы и метод " между?'

Это просто пример, в реальной жизни вы будете использовать классы, которые описывают, что они хранят:

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 "или" путь Ruby", чтобы получить правильное представление о силе языка.