¿Cómo elimino elementos en blanco de una matriz?

284

Tengo la siguiente matriz

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

Quiero eliminar elementos en blanco de la matriz y quiero el siguiente resultado:

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

¿Hay algún método como compactese que lo haga sin bucles?

ashisrai_
fuente

Respuestas:

501

Hay muchas maneras de hacer esto, una es reject

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

También puede usar reject!, que se modificará citiesen su lugar. Volverá citiescomo su valor de retorno si rechazó algo, o nilsi no se hacen rechazos. Eso puede ser un problema si no tienes cuidado (gracias a ninja08 por señalar esto en los comentarios).

Matt Greer
fuente
227
O si prefiere más compactocities.reject!(&:empty?)
aNoble
53
¿por qué no cities.reject!(&:blank?)? empty?es para matrices
Nico
27
@Nico blank?solo está disponible a través de ActiveSupport. Standard Ruby usa String#empty?: ruby-doc.org/core-1.9.3/String.html#method-i-empty-3F
Michael Kohl
24
rejectes mejor que reject!porque [].reject!(&:empty?)regresa nil, [].reject(&:empty?)regresa[]
konyak
17
cuidado con rechazar! ¡rechazar! devolverá nil si no se realizan cambios en la matriz. Si desea devolver la matriz cuando no se han realizado cambios, simplemente use el rechazo sin la explosión.
Nick Res
164
1.9.3p194 :001 > ["", "A", "B", "C", ""].reject(&:empty?)

=> ["A", "B", "C"]
usuario2010324
fuente
55
Preferiría usar .reject (&: blank?) Para evitar valores nulos también
ran632
44
@RanGalili blank?es una buena opción, pero es un railsmétodo, y esta pregunta se refiere a la llanuraruby
intercambia el
83

Esto es lo que funciona para mí:

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

salida:

[1, 2, "hello"]
kimerseen
fuente
En Ruby 2.3.1 obtengo NoMethodError: "método indefinido` ¿en blanco? ' para 1: Fixnum "tratando de ejecutar esto.
Tom
1
@ Tom en blanco? es un método específico de Rails. No existe en Array para rubí simple. Tendrás que usar vacío? o escribe tu propio método.
jpgeek
@jpgeek Gracias por la aclaración, ese fue el problema que estaba teniendo al darme cuenta de que :blank?es específico de Rails.
Tom
Porque NoMethodError: undefined method empty? for nil:NilClass, :blank? es mejor que:empty?
Lane
:blankfunciona mejor que :empty. Porque :emptyno funciona paranil
KBIIX
54

En mi proyecto uso delete:

cities.delete("")
esio
fuente
55
¡elegante! por desgracia no devuelve la matriz restante, pero bastante resbaladiza
Kevin
11
Array.delete es contra intuitivo. Funciona como un .delete! () Si tal método existiera. El .delete () opera directamente en la matriz de manera destructiva.
scarver2
41

Cuando quiero ordenar una matriz como esta, uso:

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

Esto eliminará todos los elementos en blanco o nulos.

superluminario
fuente
1
En realidad, la respuesta de The Tin Man es mejor, ya que también eliminará todo lo que coincida con Object # blank. es decir, nil, "", "\ n", "", "\ n \ r", etc. A diferencia de la respuesta aceptada, también funcionará sin Rails.
superluminary
24

Más explícito

cities.delete_if(&:blank?)

Esto eliminará los nilvalores y los valores de cadena ( "") vacíos .

Por ejemplo:

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

cities.delete_if(&:blank?)
# => ["Kathmandu", "Pokhara", "Dharan", "Butwal"]
phlegx
fuente
Al eliminar la puntuación y agregar dos puntos
aparece
2
en blanco es un método de rubí o rieles?
Arnold Roa
2
@ArnoldRoa Es un método Rails.
PaulMest
1
¿Qué pasa si hay un espacio entre la cadena vacía?
Steven Aguilar
@StevenAguilar un espacio se considera como longitud 1 (porque un espacio es un carácter). " ".¿blanco? => falso
phlegx
23

Prueba esto:

puts ["Kathmandu", "Pokhara", "", "Dharan", "Butwal"] - [""]
Raels
fuente
44
¡Esto es resbaladizo y no regresa ""! Este es un gran truco lil.
Sean Larkin
2
["Katmandú", "Pokhara", "", "Dharan", "Butwal"] - [""] - no funcionará en este caso
ajahongir
2.0.0-p247: 001> ["Katmandú", "Pokhara", "", "Dharan", "Butwal"] - [""] => ["Katmandú", "Pokhara", "Dharan", "Butwal "] Parece funcionar para mi. ¿Por qué crees que no funciona?
Raels
1
@Raels, la cadena en blanco en este caso no está vacía. Tiene un solo espacio dentro de él.
Chandranshu
1
@Chandranshu ruego diferir. Copié y pegué el texto en un editor y descubrí que no había espacio entre las comillas como usted sugirió. Si lo hubiera, restar ["", ""] funcionaría. El ejemplo de Superluminary es similar y funciona también. La solicitud original era eliminar "elementos en blanco", no "elementos en blanco", y el elemento en blanco de ejemplo se mostró en el OP como "".
Raels
17

Uso reject:

>> cities = ["Kathmandu", "Pokhara", "", "Dharan", "Butwal"].reject{ |e| e.empty? }
=> ["Kathmandu", "Pokhara", "Dharan", "Butwal"]
el hombre de hojalata
fuente
13
O, como se ha indicado anteriormente aNoble, reject(&:empty?).
mu es demasiado corto
Symbol to proc es más lento en 1.8.7 que el formato de bloque. Está a la par de lo que he visto en 1.9.2
Caley Woods
Esto es bueno ya que eliminará cualquier elemento que coincida con Object # empty ?, por ejemplo. "\ n", "", nil, "\ n \ n \ n", etc ...
superluminary
55
nil.empty?ruptura de la pluma!
Naveed
1
@AllenMaxwell @Naveed Si su matriz tiene elementos nulos, preceda reject(&:empty?)con, compactpor ejemplo,[nil, ''].compact.reject(&:empty?)
scarver2
14
cities.reject! { |c| c.blank? }

La razón por la que desea utilizar blank?más empty?es que reconoce en blanco nula, cadenas vacías, y un espacio en blanco. Por ejemplo:

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

aún regresaría:

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

Y volverá empty?a llamar , lo que probablemente quieras ser ." "falsetrue

Nota: blank?solo se puede acceder a través de Rails, Ruby solo es compatible empty?.

Colton Fent
fuente
11

Ya hay muchas respuestas, pero aquí hay otro enfoque si estás en el mundo de Rails:

 cities = ["Kathmandu", "Pokhara", "", "Dharan", "Butwal"].select &:present?
Naveed
fuente
44
present?proviene de ActiveSupport. Esto tiene una etiqueta sin Rails y requiere una gema extra para un método parece excesivo.
Michael Kohl
1
@Naveed, debe prefacio esto con "Si está utilizando RoR". No lo rechazaré porque todavía es información útil para principiantes.
pixelearth
9

Aquí hay un enfoque más para lograr esto

podemos usar presenceconselect

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

cities.select(&:presence)

["Kathmandu", "Pokhara", "Dharan", "Butwal"]
Sampat Badhe
fuente
2
Gracias por esto. Tenía algunos " "elementos en mi matriz que no se eliminaron con el método de rechazo. Su método eliminado nil ""o " "artículos.
iamse7en
8

Aquí hay una solución si tiene tipos mixtos en su matriz:

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

Solución:

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

Salida:

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

Puedes probar esto

 cities.reject!(&:empty?)
anusha
fuente
3
tal vez cities.reject!(&:blank?)
quisiste
2
 cities = ["Kathmandu", "Pokhara", "", "Dharan", "Butwal"].delete_if {|c| c.empty? } 
suren
fuente
eliminar y organizar sería una operación costosa
Naveed
2

Camino más corto cities.select(&:present?)

Javier Segovia
fuente
0

otro método:

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

Actualizar con un estricto con join&split

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

El resultado será:

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

Tenga en cuenta que: esto no funciona con una ciudad con espacios

Hieu Pham
fuente
2
¡Parece muy arriesgado!
msdundar
1
Esto definitivamente fallará si tienes una ciudad como "Nueva York" o "Naujoji Akmene" :)
Petras L