Другим другим способом решения этой проблемы является использование нового (относительно этого вопроса) Enumerator::Lazy
:
def example
@lines.lazy
.select { |line| line.property == requirement }
.map { |line| transforming_method(line) }
.uniq
.sort
end
Метод .lazy
возвращает ленивый перечислитель.Вызов .select
или .map
для ленивого перечислителя возвращает другой ленивый перечислитель.Только после того, как вы вызовете .uniq
, он на самом деле вызывает перечислитель и возвращает массив.Итак, что действительно происходит, так это то, что ваши .select
и .map
вызовы объединяются в один - вы просто перебираете @lines
один раз, чтобы выполнить и .select
, и .map
.
Мой инстинкт заключается в том, что АдамМетод 1016 * будет немного быстрее, но я думаю, что он гораздо более читабелен.
Основным следствием этого является то, что промежуточные объекты массива не создаются для каждого последующего вызова метода.В обычной ситуации @lines.select.map
, select
возвращает массив, который затем изменяется на map
, снова возвращая массив.Для сравнения, ленивая оценка создает массив только один раз.Это полезно, когда ваш начальный объект коллекции большой.Это также дает вам возможность работать с бесконечными счетчиками - например, random_number_generator.lazy.select(&:odd?).take(10)
.