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

284

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

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

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

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

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

ashisrai_
источник

Ответы:

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"]
user2010324
источник
5
Я бы предпочел использовать .reject (&: blank?), Чтобы также избежать значений nil
ran632
4
@RanGalili blank?- хороший выбор, но это railsметод, и этот вопрос относится к равнинеruby
Swaps
83

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

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

вывод:

[1, 2, "hello"]
kimerseen
источник
В 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("")
esio
источник
5
элегантный! к сожалению, не возвращает оставшийся массив, но довольно гладко
Кевин
11
Array.delete нелогичен. Он работает как .delete! (), Если такой метод существует. .Delete () действует прямо на массив разрушительным образом.
scarver2
41

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

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

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

superluminary
источник
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"]
phlegx
источник
Удаление пунктуации и добавление двоеточия дает «Города: удалить, если пусто»: D
clapp
2
пусто метод рубин или рельсы?
Арнольд Роа
2
@ArnoldRoa Это метод Rails.
PaulMest
1
Что делать, если между пустой строкой есть пробел?
Стивен Агилар
@StevenAguilar пробел считается длиной 1 (потому что пробел является символом). ".blank? => false
флегкс
23

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

puts ["Kathmandu", "Pokhara", "", "Dharan", "Butwal"] - [""]
Raels
источник
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]
Francois
источник
5

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

 cities.reject!(&:empty?)
Anusha
источник
3
может быть, вы имели в видуcities.reject!(&:blank?)
xguox
2
 cities = ["Kathmandu", "Pokhara", "", "Dharan", "Butwal"].delete_if {|c| c.empty? } 
Сурен
источник
удаление и организация будет дорогостоящей операцией
Naveed
2

Кратчайший путь cities.select(&:present?)

Хавьер Сеговия
источник
0

другой метод:

> ["a","b","c","","","f","g"].keep_if{|some| some.present?}
=> ["a","b","c","f","g"]
p4ndepravity
источник
-2

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

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

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

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

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

Хиеу Фам
источник
2
Выглядит очень рискованно!
мсдундар
1
Это определенно потерпит неудачу, если у вас есть такой город, как «Нью-Йорк» или «Naujoji Akmene» :)
Petras L