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

Я бы рекомендовал использовать PDO (объекты данных PHP) для запуска параметризованных SQL-запросов.

Это не только защищает от SQL-инъекции, но и ускоряет выполнение запросов.

И используя функции PDO, а не mysql_, mysqli_ и pgsql_, вы делаете свое приложение немного более абстрактным из базы данных, в редких случаях, когда вам нужно переключать поставщиков баз данных .

86
задан hlovdal 26 December 2010 в 14:30
поделиться

8 ответов

Если Вы действительно хотите, можно создать метод Array#comprehend как это:

class Array
  def comprehend(&block)
    return self if block.nil?
    self.collect(&block).compact
  end
end

some_array = [1, 2, 3, 4, 5, 6]
new_array = some_array.comprehend {|x| x * 3 if x % 2 == 0}
puts new_array

Печать:

6
12
18

я, вероятно, просто сделал бы это способ, которым Вы сделали все же.

53
ответ дан Robert Gamble 24 November 2019 в 07:58
поделиться

Как насчет:

some_array.map {|x| x % 2 == 0 ? x * 3 : nil}.compact

Немного инструмент для очистки, по крайней мере, к моему вкусу, и согласно быстрому эталонному тестированию приблизительно на 15% быстрее, чем Ваша версия...

84
ответ дан glenn mcdonald 24 November 2019 в 07:58
поделиться

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

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

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

-3
ответ дан 24 November 2019 в 07:58
поделиться

Я обсуждал эту тему с Рейном Хенриксом, который сказал мне, что наиболее эффективным решением является

map { ... }.compact`

Это имеет смысл, потому что оно избегает создания промежуточных массивов, как при неизменном использовании Enumerable#inject, и это позволяет избежать роста Массива, что вызывает выделение. Он так же общий, как и любой другой, если ваша коллекция не может содержать нулевых элементов.

Я не сравнивал это с

select {...}.map{...}

Возможно, что реализация Ruby на C Enumerable#select также очень хороша.

11
ответ дан 24 November 2019 в 07:58
поделиться
[1, 2, 3, 4, 5, 6].collect{|x| x * 3 if x % 2 == 0}.compact
=> [6, 12, 18]

У меня это работает. Это тоже чисто. Да, это то же самое, что и map , но я думаю, что collect делает код более понятным.


select(&:even?).map()

действительно выглядит лучше, после того, как увидит это ниже.

4
ответ дан 24 November 2019 в 07:58
поделиться
​​

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

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

2
ответ дан 24 November 2019 в 07:58
поделиться

Это более лаконично:

[1,2,3,4,5,6].select(&:even?).map{|x| x*3}
4
ответ дан 24 November 2019 в 07:58
поделиться

Альтернативное решение который будет работать в каждой реализации и запускаться за O (n) вместо O (2n). Время:

some_array.inject([]){|res,x| x % 2 == 0 ? res << 3*x : res}
9
ответ дан 24 November 2019 в 07:58
поделиться
Другие вопросы по тегам:

Похожие вопросы: