Предоставить Proc для метода в качестве блока

StackOverflow https://stackoverflow.com/questions/3960573

  •  09-10-2019
  •  | 
  •  

Вопрос

Скажем, у меня есть следующий массив:

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

Более общее решение проблем, подобных этим, - это исключить вложенные массивы и использовать вместо этого класса. Затем вы можете определить оператор <=> для этого класса, предоставляя вам доступ ко всем функциям в сопоставимом микене (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 и сортировки без необходимости определения оператора сравнения. Так...

@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» или «Рубиный путь», чтобы получить правильный обзор силы языка.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top