Como faço para remover elementos em branco de uma matriz?

284

Eu tenho a seguinte matriz

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

Desejo remover elementos em branco da matriz e quero o seguinte resultado:

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

Existe algum método assim compactque o faça sem loops?

ashisrai_
fonte

Respostas:

501

Existem muitas maneiras de fazer isso, uma é reject

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

Você também pode usar reject!, que será modificado citiesno local. Ele retornará citiescomo seu valor de retorno se rejeitar alguma coisa ou nilse nenhuma rejeição for feita. Isso pode ser um problema, se você não tomar cuidado (obrigado a ninja08 por apontar isso nos comentários).

Matt Greer
fonte
227
Ou se preferir mais compactocities.reject!(&:empty?)
aNoble
53
hm, porque não cities.reject!(&:blank?)? empty?é para matrizes
Nico
27
O @Nico blank?está disponível apenas através ActiveSupport. Padrão Ruby faz uso String#empty?: ruby-doc.org/core-1.9.3/String.html#method-i-empty-3F
Michael Kohl
24
rejecté melhor do que reject!porque [].reject!(&:empty?)retornos nil, [].reject(&:empty?)retornos[]
konyak
17
cuidado com rejeitar !. rejeitar! retornará nulo se nenhuma alteração for feita na matriz. Se você quiser retornar a matriz quando nenhuma alteração tiver sido feita, use rejeitar sem o estrondo.
Nick Res
164
1.9.3p194 :001 > ["", "A", "B", "C", ""].reject(&:empty?)

=> ["A", "B", "C"]
user2010324
fonte
5
Eu preferiria usar .reject: para evitar valores nulos, bem como (& branco?)
ran632
4
@RanGalili blank?é uma boa escolha, mas é um railsmétodo, e esta pergunta é sobre a planícieruby
Swaps
83

Aqui está o que funciona para mim:

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

resultado:

[1, 2, "hello"]
kimerseen
fonte
No Ruby 2.3.1, recebo NoMethodError: "método indefinido` blank? ' para 1: Fixnum "tentando executar isso.
6243 Tom
1
@ Tom em branco? é um método específico do Rails. Não existe na matriz para ruby ​​comum. Você terá que usar vazio? ou escreva seu próprio método.
jpgeek
@jpgeek Obrigado pelo esclarecimento, esse foi o problema que eu estava tendo ao perceber que :blank?é específico do Rails.
Tom
Porque NoMethodError: undefined method empty? for nil:NilClass, :blank? é melhor que:empty?
Lane
:blankfunciona melhor que :empty. Porque :emptynão funciona paranil
KBIIX
54

No meu projeto eu uso delete:

cities.delete("")
esio
fonte
5
elegante! infelizmente não retorna a matriz restante, mas muito escorregadio
Kevin
11
O Array.delete é contra-intuitivo. Ele funciona como um .delete! () Se esse método existir. O .delete () opera diretamente na matriz de maneira destrutiva.
scarver2
41

Quando eu quero arrumar uma matriz como esta, eu uso:

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

Isso removerá todos os elementos em branco ou nulos.

superluminário
fonte
1
Na verdade, a resposta do Homem de Lata é melhor, pois também removerá qualquer coisa que corresponda ao Objeto # em branco? nulo, "", "\ n", "", "\ n \ r", etc. Diferentemente da resposta aceita, ele também funcionará sem o Rails.
superluminary
24

Mais explícito

cities.delete_if(&:blank?)

Isso removerá os nilvalores e os valores vazios de string ( "").

Por exemplo:

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

cities.delete_if(&:blank?)
# => ["Kathmandu", "Pokhara", "Dharan", "Butwal"]
flegx
fonte
Remover a pontuação e adicionar dois pontos indica "Cidades: excluir se estiver em branco": D
clapp
2
blank é um método ruby ​​ou rails?
Arnold Roa
2
@ArnoldRoa É um método Rails.
PaulMest 8/02/16
1
e se houver um espaço entre a string vazia?
Steven Aguilar
@StevenAguilar um espaço é considerado como comprimento 1 (porque um espaço é um caractere). "" .blank? => false
phlegx 4/17/17
23

Tente o seguinte:

puts ["Kathmandu", "Pokhara", "", "Dharan", "Butwal"] - [""]
Raels
fonte
4
Isso é liso e não retorna ""! Este é um ótimo truque de lil.
21813 Sean Larkin
2
["Kathmandu", "Pokhara", "", "Dharan", "Butwal"] - [""] - não funcionará neste caso
ajahongir
2.0.0-p247: 001> ["Catmandu", "Pokhara", "", Dharan "," Butwal "] - [" "] => [" Catmandu "," Pokhara "," Dharan "e" Butwal "] Parece funcionar para mim. Por que você acha que isso não funciona?
Raels 30/10
1
@ Raels, a string em branco neste caso não está vazia. Tem um único espaço dentro dele.
Chandranshu
1
@ Chandranshu Eu imploro para diferir. Copiei e colei o texto em um editor e descobri que não havia espaço entre as aspas, como você sugeriu. Se houvesse, subtrair ["", ""] funcionaria. O exemplo do superluminário é semelhante e funciona também. A solicitação original era remover "elementos em branco" e não "elementos em branco" e o exemplo de elemento em branco foi mostrado no OP como "".
Raels
17

Use reject:

>> cities = ["Kathmandu", "Pokhara", "", "Dharan", "Butwal"].reject{ |e| e.empty? }
=> ["Kathmandu", "Pokhara", "Dharan", "Butwal"]
o homem de lata
fonte
13
Ou, como um nooble observou acima reject(&:empty?),.
mu é muito curto
O símbolo para proc é mais lento no 1.8.7 que o formato do bloco. É a par do que eu vi em 1.9.2
Caley Woods
Isso é bom, pois removerá qualquer elemento que corresponda ao Objeto # vazio ?, por exemplo. "\ n", "", zero, "\ n \ n \ n", etc ...
superluminary
5
nil.empty?booom break!
Naveed
1
@AllenMaxwell @Naveed Se sua matriz tiver elementos nulos, anteceda o reject(&:empty?)com, compactpor exemplo,[nil, ''].compact.reject(&:empty?)
scarver2
14
cities.reject! { |c| c.blank? }

O motivo pelo qual você deseja usar blank?mais empty?é que o espaço em branco reconhece nada, cadeias vazias e espaços em branco. Por exemplo:

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

ainda retornaria:

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

E chamando empty?no " "retorno vontade false, que você provavelmente vai querer ser true.

Nota: blank?só é acessível através do Rails, o Ruby suporta apenas empty?.

Colton Fent
fonte
11

Já existem muitas respostas, mas aqui está outra abordagem, se você estiver no mundo do Rails:

 cities = ["Kathmandu", "Pokhara", "", "Dharan", "Butwal"].select &:present?
Naveed
fonte
4
present?vem de ActiveSupport. Isso tem uma tag no Rails, e exigir uma gema extra para um método parece excessivo.
22612 Michael Kohl
1
@Naveed, você deve preceder isso com "Se você estiver usando o RoR". Não vou diminuir o voto, porque ainda são informações úteis para iniciantes.
precisa saber é o seguinte
9

Aqui está mais uma abordagem para alcançar esse objetivo.

nós podemos usar presencecomselect

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

cities.select(&:presence)

["Kathmandu", "Pokhara", "Dharan", "Butwal"]
Sampat Badhe
fonte
2
Obrigado por isso. Eu tinha alguns " "elementos em minha matriz que não foram removidos com o método rejeitar. Seu método removido nil ""ou " "itens.
iamse7en
8

Aqui está uma solução se você tiver tipos mistos em sua matriz:

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

Solução:

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

Resultado:

=> ["some string here", 4, 3, 2]
François
fonte
5

Você pode tentar isso

 cities.reject!(&:empty?)
anusha
fonte
3
talvez você quis dizer #cities.reject!(&:blank?)
1100 xguox
2
 cities = ["Kathmandu", "Pokhara", "", "Dharan", "Butwal"].delete_if {|c| c.empty? } 
suren
fonte
apagar e organizar seria uma operação dispendiosa
Naveed
2

Maneira mais curta cities.select(&:present?)

Javier Segovia
fonte
0

outro método:

> ["a","b","c","","","f","g"].keep_if{|some| some.present?}
=> ["a","b","c","f","g"]
p4ndepravity
fonte
-2

Atualize com um rigoroso com join&split

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

O resultado será:

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

Observe que: isso não funciona com uma cidade com espaços

Hieu Pham
fonte
2
Parece muito arriscado!
msdundar
1
Definitivamente, isso falhará se você tiver uma cidade como "Nova York" ou "Naujoji Akmene" :)
Petras L