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?

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


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

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

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

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.


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

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

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

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


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?

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

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]

5

Vous pouvez essayer ceci

 cities.reject!(&:empty?)

3
peut-être que tu voulais direcities.reject!(&:blank?)
xguox

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

supprimer et organiser serait une opération coûteuse
Naveed


0

une autre méthode:

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

-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


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
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.