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

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


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

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

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

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.


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

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

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

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


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?

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

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]


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

eliminar y organizar sería una operación costosa
Naveed


0

otro método:

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

-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


2
¡Parece muy arriesgado!
msdundar

1
Esto definitivamente fallará si tienes una ciudad como "Nueva York" o "Naujoji Akmene" :)
Petras L
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.