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?

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).


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"]

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"]

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("")

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.


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"]

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"] - [""]

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"]

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?.


11

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

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

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"]

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]

5

Você pode tentar isso

 cities.reject!(&:empty?)

3
talvez você quis dizer #cities.reject!(&:blank?)
1100 xguox

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

apagar e organizar seria uma operação dispendiosa
Naveed


0

outro método:

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

-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


2
Parece muito arriscado!
msdundar

1
Definitivamente, isso falhará se você tiver uma cidade como "Nova York" ou "Naujoji Akmene" :)
Petras L
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.