Как удалить пустые элементы из массива?


284

У меня есть следующий массив

cities = ["Kathmandu", "Pokhara", "", "Dharan", "Butwal"]

Я хочу удалить пустые элементы из массива и хочу следующий результат:

cities = ["Kathmandu", "Pokhara", "Dharan", "Butwal"]

Есть ли такой способ compactсделать это без петель?

Ответы:


501

Есть много способов сделать это, один reject

noEmptyCities = cities.reject { |c| c.empty? }

Вы также можете использовать reject!, который будет изменять citiesна месте. Он либо вернет citiesсвое возвращаемое значение, если он что-то отклонил, либо nilесли отклонения не сделаны. Это может быть ошибкой, если вы не будете осторожны (спасибо ninja08 за то, что отметили это в комментариях).


227
Или, если вы предпочитаете более компактныйcities.reject!(&:empty?)
Благородный

53
хм, а почему бы и нет cities.reject!(&:blank?)? empty?для массивов
Нико

27
@Nico blank?доступен только через ActiveSupport. Стандартный Ruby использует String#empty?: ruby-doc.org/core-1.9.3/String.html#method-i-empty-3F
Майкл Кол,

24
rejectлучше чем reject!потому что [].reject!(&:empty?)возвращается nil, [].reject(&:empty?)возвращается[]
коняк

17
Берегись с отклонением !. отказаться! вернет ноль, если в массив не внесены изменения. Если вы хотите вернуть массив, когда не было внесено никаких изменений, просто используйте отклонение без взрыва.
Ник Рез

164
1.9.3p194 :001 > ["", "A", "B", "C", ""].reject(&:empty?)

=> ["A", "B", "C"]

5
Я бы предпочел использовать .reject (&: blank?), Чтобы также избежать значений nil
ran632

4
@RanGalili blank?- хороший выбор, но это railsметод, и этот вопрос относится к равнинеruby
Swaps

83

Вот что работает для меня:

[1, "", 2, "hello", nil].reject(&:blank?)

вывод:

[1, 2, "hello"]

В Ruby 2.3.1 я получаю NoMethodError: "неопределенный метод" blank? " для 1: Fixnum "пытается выполнить это.
Том

1
@ Пусто? специфичный для Rails метод Не существует в массиве для обычного рубина. Вам придется использовать пустой? или напишите свой собственный метод.
jpgeek

@jpgeek Спасибо за разъяснения, это была проблема, с которой я столкнулся при реализации :blank?, специфичной для Rails.
Том

Потому что NoMethodError: undefined method empty? for nil:NilClass, :blank? лучше:empty?
Лейн

:blankработает лучше чем :empty. Потому :emptyчто не работает дляnil
KBIIX

54

В моем проекте я использую delete:

cities.delete("")

5
элегантный! к сожалению, не возвращает оставшийся массив, но довольно гладко
Кевин

11
Array.delete нелогичен. Он работает как .delete! (), Если такой метод существует. .Delete () действует прямо на массив разрушительным образом.
scarver2

41

Когда я хочу привести в порядок массив, я использую:

["Kathmandu", "Pokhara", "", "Dharan", "Butwal"] - ["", nil]

Это удалит все пустые или нулевые элементы.


1
На самом деле, ответ The Tin Man лучше, так как он также удалит что-нибудь, что соответствует Object # blank? т.е. nil, "", "\ n", "", "\ n \ r" и т. д. В отличие от принятого ответа, он также будет работать без Rails.
Сверхсветовой

24

Наиболее явный

cities.delete_if(&:blank?)

Это удалит как nilзначения, так и пустые значения string ( "").

Например:

cities = ["Kathmandu", "Pokhara", "", "Dharan", "Butwal", nil]

cities.delete_if(&:blank?)
# => ["Kathmandu", "Pokhara", "Dharan", "Butwal"]

Удаление пунктуации и добавление двоеточия дает «Города: удалить, если пусто»: D
clapp

2
пусто метод рубин или рельсы?
Арнольд Роа

2
@ArnoldRoa Это метод Rails.
PaulMest

1
Что делать, если между пустой строкой есть пробел?
Стивен Агилар

@StevenAguilar пробел считается длиной 1 (потому что пробел является символом). ".blank? => false
флегкс

23

Попробуй это:

puts ["Kathmandu", "Pokhara", "", "Dharan", "Butwal"] - [""]

4
Это гладко, и не возвращает ""! Это отличный трюк.
Шон Ларкин

2
["Kathmandu", "Pokhara", "", "Dharan", "Butwal"] - [""] - не будут работать в этом случае
ajahongir

2.0.0-p247: 001> ["Катманду", "Покхара", "", "Дхарана", "Бутвал"] - [""] => ["Катманду", "Покхара", "Дхарана", "Бутвал" "] Кажется, работает на меня. Как вы думаете, почему это не работает?
Раэльс

1
@Raels, пустая строка в этом случае не пустая. У него есть одно пространство внутри.
Чандраншу

1
@Chandranshu Я прошу отличаться. Я скопировал и вставил текст в редактор и обнаружил, что между кавычками нет места, как вы предложили. Если бы было, то вычитание ["", ""] сработало бы. Пример суперсветильности похож и работает так же. Первоначальный запрос заключался в том, чтобы удалить «пустые элементы», а не «элементы, которые являются пробелами», и пример пустого элемента был показан в OP как «».
Раэльс

17

Используйте reject:

>> cities = ["Kathmandu", "Pokhara", "", "Dharan", "Butwal"].reject{ |e| e.empty? }
=> ["Kathmandu", "Pokhara", "Dharan", "Butwal"]

13
Или, как было отмечено выше aNoble, reject(&:empty?).
мю слишком коротка

Символ в proc медленнее в 1.8.7, чем формат блока. Это на одном уровне с тем, что я видел в 1.9.2
Кейли Вудс

Это хорошо, так как удалит любой элемент, который соответствует Object # empty?, Например. "\ n", "", nil, "\ n \ n \ n" и т. д.
сверхсветовой

5
nil.empty?бум перерыв!
Навид

1
@AllenMaxwell @Naveed Если массив имеет нулевые элементы, предшествуют reject(&:empty?)с , compactнапример[nil, ''].compact.reject(&:empty?)
scarver2

14
cities.reject! { |c| c.blank? }

Причина, по которой вы хотите использовать blank?более, empty?заключается в том, что пробел распознает ноль, пустые строки и пробелы. Например:

cities = ["Kathmandu", "Pokhara", " ", nil, "", "Dharan", "Butwal"].reject { |c| c.blank? }

все равно вернется

["Kathmandu", "Pokhara", "Dharan", "Butwal"]

И , призвав empty?на " "ВЕРНЕТСЯ false, который вы , вероятно , хотите быть true.

Примечание: blank?доступно только через Rails, Ruby поддерживает только empty?.


11

Ответов уже много, но вот другой подход, если вы находитесь в мире Rails:

 cities = ["Kathmandu", "Pokhara", "", "Dharan", "Butwal"].select &:present?

4
present?приходит от ActiveSupport. У него нет тега Rails, и требование дополнительного гема для одного метода кажется чрезмерным.
Майкл Кол

1
@Naveed, вы должны предварить это "Если вы используете RoR". Я не буду отрицать это, потому что это все еще полезная информация для начинающих.
pixelearth

9

Вот еще один подход для достижения этой цели

мы можем использовать presenceсselect

cities = ["Kathmandu", "Pokhara", "", "Dharan", nil, "Butwal"]

cities.select(&:presence)

["Kathmandu", "Pokhara", "Dharan", "Butwal"]

2
Спасибо тебе за это. " "В моем массиве были некоторые элементы, которые не были удалены с помощью метода отклонения. Ваш метод удален nil ""или " "элементы.
iamse7en

8

Вот решение, если у вас есть смешанные типы в вашем массиве:

[nil,"some string here","",4,3,2]

Решение:

[nil,"some string here","",4,3,2].compact.reject{|r| r.empty? if r.class == String}

Вывод:

=> ["some string here", 4, 3, 2]

5

Вы можете попробовать это

 cities.reject!(&:empty?)

3
может быть, вы имели в видуcities.reject!(&:blank?)
xguox

2
 cities = ["Kathmandu", "Pokhara", "", "Dharan", "Butwal"].delete_if {|c| c.empty? } 

удаление и организация будет дорогостоящей операцией
Naveed



-2

Обновление со строгим с join&split

cities = ["Kathmandu", "Pokhara", "", "Dharan", "Butwal"]
cities.join(' ').split

Результат будет:

["Kathmandu", "Pokhara", "Dharan", "Butwal"]

Обратите внимание: это не работает с городом с пробелами


2
Выглядит очень рискованно!
мсдундар

1
Это определенно потерпит неудачу, если у вас есть такой город, как «Нью-Йорк» или «Naujoji Akmene» :)
Petras L
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.