Понимание списка в Ruby - PullRequest
       73

Понимание списка в Ruby

85 голосов
/ 22 ноября 2008

Чтобы сделать эквивалентность понимания списка Python, я делаю следующее:

some_array.select{|x| x % 2 == 0 }.collect{|x| x * 3}

Есть ли лучший способ сделать это ... возможно, с помощью одного вызова метода?

Ответы [ 14 ]

2 голосов
/ 17 апреля 2013

Примерно так:

def lazy(collection, &blk)
   collection.map{|x| blk.call(x)}.compact
end

Назовите это:

lazy (1..6){|x| x * 3 if x.even?}

Что возвращает:

=> [6, 12, 18]
2 голосов
/ 03 мая 2010

Как упомянуто Педро, вы можете объединить цепочки вызовов в Enumerable#select и Enumerable#map, избегая обхода выбранных элементов. Это верно, потому что Enumerable#select является специализацией сгиба или inject. Я опубликовал поспешное введение к теме в субреддите Ruby.

Ручное слияние преобразований Array может быть утомительным, поэтому, возможно, кто-то может поиграть с реализацией comprehend Роберта Гэмбла, чтобы сделать этот шаблон select / map красивее.

1 голос
/ 30 октября 2018

Другое решение, но, возможно, не самое лучшее

some_array.flat_map {|x| x % 2 == 0 ? [x * 3] : [] }

или

some_array.each_with_object([]) {|x, list| x % 2 == 0 ? list.push(x * 3) : nil }
0 голосов
/ 24 октября 2009

Я думаю, что наиболее подходящим для понимания списка было бы следующее:

some_array.select{ |x| x * 3 if x % 2 == 0 }

Поскольку Ruby позволяет нам помещать условное выражение после выражения, мы получаем синтаксис, аналогичный Python-версии понимания списка. Кроме того, поскольку метод select не включает ничего, равного false, все значения nil удаляются из результирующего списка, и не требуется никакого вызова для сжатия, как в случае, если бы мы использовали map или collect вместо.

...