Как я могу улучшить код для удаления элементов в массиве в следующем случае? - PullRequest
1 голос
/ 05 февраля 2011

У меня есть этот код:

array = ['notice', 'warning', 'error']

array.delete('notice')  if flash[:notice]
array.delete('warning') if flash[:warning]
array.delete('error')   if flash[:error]

Поскольку существуют повторяющиеся имена, для сокращения кода я мог бы использовать интерполяцию для выполнения этой части кода:

array.delete('notice')  if flash[:notice]
array.delete('warning') if flash[:warning]
array.delete('error')   if flash[:error]

Как я могу сделать это за один шаг?


Я пробовал это

array.each { |item|
  array.delete("#{item}") if flash[:"#{item}"]
}

, но это не работает хорошо.

Ответы [ 3 ]

1 голос
/ 05 февраля 2011
array.reject! { |item| flash[item.to_sym] }
0 голосов
/ 05 февраля 2011

Вам не нужно использовать интерполяцию строк, просто преобразуйте строки в символы, используя .to_sym:

array = ['notice', 'warning', 'error']
array.each { |item|
    array.delete(item) if flash[item.to_sym]
}

Или используйте символы от array до .to_s при удалении:

array = [:notice, :warning, :error]
array.each { |item|
    array.delete(item.to_s) if flash[item]
}
0 голосов
/ 05 февраля 2011

Это происходит из-за того, что вы модифицируете массив, для которого вы выполняете итерацию.
Что-то вроде этого должно работать

array.clone.each { |item|
  array.delete("#{item}") if flash[:"#{item}"]
}

Попробуйте запустить его с * 1005 и без * на вводе образца

array = ['notice', 'warning', 'error']
flash = {:warning => 1, :error => 2}

...

p array

Но нет необходимости вызывать delete вручную, вы можете просто использовать пользователя reject :

array = array.reject! { |item| flash[:"#{item}"] }
...