Подтвердить что ты не робот

Пропустить итерацию в Enumerable # collect

(1..4).collect do |x|
  next if x == 3
  x + 1
end # => [2, 3, nil, 5]
    # desired => [2, 3, 5]

Если условие для next выполнено, collect помещает nil в массив, тогда как то, что я пытаюсь сделать, не помещает элемент в возвращенный массив, если условие выполнено. Возможно ли это без вызова delete_if { |x| x == nil } в возвращаемом массиве?

(Использование Ruby 1.8.7, мой фрагмент кода сильно абстрагирован)

4b9b3361

Ответ 1

Существует метод Enumerable#reject, который служит только для этой цели:

(1..4).reject{|x| x == 3}.collect{|x| x + 1}

Практика прямого использования вывода одного метода в качестве входа другого называется цепью метода и очень распространена в Ruby.

BTW, map (или collect) используется для прямого отображения ввода, перечислимого на выходной. Если вам нужно вывести различное количество элементов, возможно, вам нужен другой метод Enumerable.

Изменить: Если вас беспокоит тот факт, что некоторые из элементов повторяются дважды, вы можете использовать менее элегантное решение на основе inject (или его аналогичный метод с именем each_with_object):

(1..4).each_with_object([]){|x,a| a << x + 1 unless x == 3}

Ответ 2

Я бы просто вызвал .compact в результирующем массиве, который удаляет все экземпляры nil в массиве. Если вы хотите изменить существующий массив (без причины), используйте .compact!:

(1..4).collect do |x|
  next if x == 3
  x
end.compact!

Ответ 3

просто предложение, почему бы вам не сделать так:

result = []
(1..4).each do |x|
  next if x == 3
  result << x
end
result # => [1, 2, 4]

таким образом вы сохранили другую итерацию, чтобы удалить элементы nil из массива. надеюсь, что это помогает =)

Ответ 4

я предлагаю использовать:

(1..4).to_a.delete_if {|x| x == 3}

вместо команды collect + next.

Ответ 5

Вы можете вывести принятие решения в вспомогательный метод и использовать его через Enumerable#reduce:

def potentially_keep(list, i)
  if i === 3
    list
  else
    list.push i
  end
end
# => :potentially_keep

(1..4).reduce([]) { |memo, i| potentially_keep(memo, i) }
# => [1, 2, 4]