Comment supprimer des éléments vides d'un tableau?

284

J'ai le tableau suivant

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

Je souhaite supprimer des éléments vides du tableau et souhaite le résultat suivant:

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

Existe-t-il une méthode comme compactcelle-ci qui le fera sans boucles?

ashisrai_
la source

Réponses:

501

Il y a plusieurs façons de le faire, l'une est reject

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

Vous pouvez également utiliser reject!, qui modifiera citiesen place. Il retournera soit citiessa valeur de retour s'il a rejeté quelque chose, soit nilsi aucun rejet n'est fait. Cela peut être un piège si vous ne faites pas attention (merci à ninja08 pour l'avoir signalé dans les commentaires).

Matt Greer
la source
227
Ou si vous préférez plus compactcities.reject!(&:empty?)
aNoble
53
hm, pourquoi pas cities.reject!(&:blank?)? empty?est pour les tableaux
Nico
27
@Nico blank?est uniquement disponible via ActiveSupport. Ruby standard utilise String#empty?: ruby-doc.org/core-1.9.3/String.html#method-i-empty-3F
Michael Kohl
24
rejectest mieux que reject!parce que [].reject!(&:empty?)retourne nil, [].reject(&:empty?)retourne[]
konyak
17
attention au rejet!. rejeter! renverra nil si aucune modification n'est apportée au tableau. Si vous souhaitez renvoyer le tableau lorsqu'aucune modification n'a été apportée, utilisez simplement rejet sans le bang.
Nick Res
164
1.9.3p194 :001 > ["", "A", "B", "C", ""].reject(&:empty?)

=> ["A", "B", "C"]
user2010324
la source
5
Je préférerais utiliser .reject (&: vide?) Pour éviter les valeurs nulles également
ran632
4
@RanGalili blank?est un bon choix mais c'est une railsméthode, et cette question concerne la plaineruby
Swaps
83

Voici ce qui fonctionne pour moi:

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

production:

[1, 2, "hello"]
kimerseen
la source
Sur Ruby 2.3.1, j'obtiens NoMethodError: "méthode non définie` vide? ' for 1: Fixnum "essayant d'exécuter ceci.
Tom
1
@Tom vide? est une méthode spécifique à Rails. N'existe pas sur Array pour le rubis uni. Vous devrez utiliser vide? ou écrivez votre propre méthode.
jpgeek
@jpgeek Merci pour la clarification, c'est le problème que j'ai eu à réaliser :blank?est spécifique à Rails.
Tom
Parce que NoMethodError: undefined method empty? for nil:NilClass, :blank? c'est mieux que:empty?
Lane
:blankfonctionne mieux que :empty. Parce :emptyque ne fonctionne pas pournil
KBIIX
54

Dans mon projet j'utilise delete:

cities.delete("")
esio
la source
5
élégant! ne retourne malheureusement pas le tableau restant, mais assez lisse
Kevin
11
Array.delete est contre-intuitif. Il fonctionne comme un .delete! () Si une telle méthode existait. Le .delete () opère directement sur le tableau de manière destructrice.
scarver2
41

Quand je veux ranger un tableau comme celui-ci, j'utilise:

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

Cela supprimera tous les éléments vides ou nuls.

superluminaire
la source
1
En fait, la réponse de The Tin Man est meilleure car elle supprimera également tout ce qui correspond à l'objet # vide? ie nil, "", "\ n", "", "\ n \ r", etc. Contrairement à la réponse acceptée, cela fonctionnera également sans Rails.
superluminaire
24

Le plus explicite

cities.delete_if(&:blank?)

Cela supprimera les nilvaleurs et les valeurs de chaîne ( "") vides .

Par exemple:

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

cities.delete_if(&:blank?)
# => ["Kathmandu", "Pokhara", "Dharan", "Butwal"]
phlegx
la source
La suppression de la ponctuation et l'ajout de deux points donnent "Cities: delete if blank": D
clapp
2
blanc est une méthode rubis ou rails?
Arnold Roa
2
@ArnoldRoa C'est une méthode Rails.
PaulMest
1
que faire s'il y a un espace entre la chaîne vide?
Steven Aguilar
@StevenAguilar un espace est considéré comme une longueur 1 (car un espace est un personnage). " ".Vide? => false
phlegx
23

Essaye ça:

puts ["Kathmandu", "Pokhara", "", "Dharan", "Butwal"] - [""]
Raels
la source
4
C'est lisse et ne renvoie pas ""! C'est un super petit truc.
Sean Larkin
2
["Katmandou", "Pokhara", "", "Dharan", "Butwal"] - [""] - ne fonctionnera pas dans ce cas
ajahongir
2.0.0-p247: 001> ["Katmandou", "Pokhara", "", "Dharan", "Butwal"] - [""] => ["Katmandou", "Pokhara", "Dharan", "Butwal "] Semble fonctionner pour moi. Pourquoi pensez-vous que cela ne fonctionne pas?
Raels
1
@Raels, la chaîne vide dans ce cas n'est pas vide. Il contient un seul espace.
Chandranshu
1
@Chandranshu Je vous prie de différer. J'ai copié et collé le texte dans un éditeur et j'ai constaté qu'il n'y avait pas d'espace entre les guillemets comme vous l'avez suggéré. S'il y en avait, alors la soustraction de ["", ""] fonctionnerait. l'exemple du superluminaire est similaire et fonctionne également. La demande initiale consistait à supprimer les "éléments vierges" et non "les éléments qui sont vierges", et l'exemple d'élément vide était indiqué dans le PO sous la forme "".
Raels
17

Utilisation reject:

>> cities = ["Kathmandu", "Pokhara", "", "Dharan", "Butwal"].reject{ |e| e.empty? }
=> ["Kathmandu", "Pokhara", "Dharan", "Butwal"]
l'homme d'étain
la source
13
Ou, comme indiqué ci - dessus aNoble, reject(&:empty?).
mu est trop court
Le symbole à proc est plus lent en 1.8.7 que le format de bloc. C'est à égalité avec ce que j'ai vu dans 1.9.2
Caley Woods
C'est bien car cela supprimera tout élément qui correspond à Object # empty?, Par exemple. "\ n", "", nil, "\ n \ n \ n", etc ...
superluminaire
5
nil.empty?pause booom!
Naveed le
1
@AllenMaxwell @Naveed Si votre tableau ne contient aucun élément, faites précéder le reject(&:empty?)par compactexemple[nil, ''].compact.reject(&:empty?)
scarver2
14
cities.reject! { |c| c.blank? }

La raison pour laquelle vous souhaitez utiliser blank?plus empty?que vide reconnaît nulle, des chaînes vides, et l' espace blanc. Par exemple:

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

reviendrait toujours:

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

Et d' appeler empty?le " "sera de retour false, que vous voulez probablement être true.

Remarque: blank?est uniquement accessible via Rails, Ruby ne prend en charge que empty?.

Colton Fent
la source
11

Il y a déjà beaucoup de réponses mais voici une autre approche si vous êtes dans le monde Rails:

 cities = ["Kathmandu", "Pokhara", "", "Dharan", "Butwal"].select &:present?
Naveed
la source
4
present?vient de ActiveSupport. Cela n'a pas de balise Rails et nécessiter une gemme supplémentaire pour une méthode semble excessif.
Michael Kohl
1
@Naveed, vous devez faire précéder ceci de "Si vous utilisez RoR". Je ne vais pas le déprécier car ce sont toujours des informations utiles pour les débutants.
pixelearth
9

Voici une autre approche pour y parvenir

nous pouvons utiliser presenceavecselect

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

cities.select(&:presence)

["Kathmandu", "Pokhara", "Dharan", "Butwal"]
Sampat Badhe
la source
2
Merci pour ça. Certains " "éléments de mon tableau n'avaient pas été supprimés avec la méthode de rejet. Votre méthode a supprimé nil ""ou des " "éléments.
iamse7en
8

Voici une solution si vous avez des types mixtes dans votre tableau:

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

Solution:

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

Production:

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

Vous pouvez essayer ceci

 cities.reject!(&:empty?)
anusha
la source
3
peut-être que tu voulais direcities.reject!(&:blank?)
xguox
2
 cities = ["Kathmandu", "Pokhara", "", "Dharan", "Butwal"].delete_if {|c| c.empty? } 
suren
la source
supprimer et organiser serait une opération coûteuse
Naveed
2

Chemin le plus court cities.select(&:present?)

Javier Segovia
la source
0

une autre méthode:

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

Mettre à jour avec un strict avec join&split

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

Le résultat sera:

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

Notez que: cela ne fonctionne pas avec une ville avec des espaces

Hieu Pham
la source
2
Ça a l'air très risqué!
msdundar
1
Cela échouera certainement si vous avez une ville comme "New York" ou "Naujoji Akmene" :)
Petras L