Ответ 1
Используйте оператор &
, чтобы превратить объект Proc
в блок.
arr.min &blo
Скажем, у меня есть следующий массив:
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
будет работать, но это не так. Любая идея о том, как я могу это сделать?
Используйте оператор &
, чтобы превратить объект 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]
Изменить: Черт, я просто заметил, что есть также 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]]
Более общее решение таких проблем заключается в том, чтобы полностью исключить вложенные массивы и вместо этого использовать класс. Затем вы можете определить оператор <= > для этого класса, предоставляя вам доступ ко всем функциям в Mixable Comparin (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 Way", чем вложенные структуры данных с логикой, которая опирается на позиции в массивах. Вначале требуется немного больше работы, но в долгосрочной перспективе вы найдете намного лучше.
Ruby - очень объектно-ориентированный язык программирования и предоставляет очень мощные инструменты для вас. Я настоятельно рекомендую прочитать книгу "Язык программирования Ruby" или "The Ruby Way", чтобы получить правильный обзор мощности языка.