Come rimuovo elementi vuoti da un array?


284

Ho il seguente array

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

Voglio rimuovere elementi vuoti dall'array e voglio il seguente risultato:

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

Esiste un metodo del genere compactche lo farà senza loop?

Risposte:


501

Ci sono molti modi per farlo, uno è reject

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

È inoltre possibile utilizzare reject!, che modificherà citiessul posto. Restituirà citiescome valore di ritorno se rifiuta qualcosa o nilse non viene fatto alcun rifiuto. Questo può essere un gotcha se non stai attento (grazie a ninja08 per averlo sottolineato nei commenti).


227
O se preferisci più compattocities.reject!(&:empty?)
aNoble

53
hm, perché no cities.reject!(&:blank?)? empty?è per array
Nico,

27
@Nico blank?è disponibile solo tramite ActiveSupport. Lo standard Ruby usa String#empty?: ruby-doc.org/core-1.9.3/String.html#method-i-empty-3F
Michael Kohl,

24
rejectè meglio che reject!perché [].reject!(&:empty?)ritorna nil, [].reject(&:empty?)ritorna[]
konyak il

17
attenzione con rifiuto !. rifiutare! restituirà zero se non vengono apportate modifiche all'array. Se si desidera restituire l'array quando non sono state apportate modifiche, utilizzare semplicemente il rifiuto senza il botto.
Nick Res

164
1.9.3p194 :001 > ["", "A", "B", "C", ""].reject(&:empty?)

=> ["A", "B", "C"]

5
Preferirei usare .reject (&: blank?) Per evitare anche valori nulli
ran632,

4
@RanGalili blank?è una buona scelta ma è un railsmetodo, e questa domanda riguarda la pianuraruby
Swap

83

Ecco cosa funziona per me:

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

produzione:

[1, 2, "hello"]

Su Ruby 2.3.1 ottengo NoMethodError: "metodo indefinito` vuoto? ' per 1: Fixnum "cercando di eseguire questo.
Tom,

1
@ Tom vuoto? è un metodo specifico di Rails. Non esiste su Array per il semplice rubino. Dovrai usare vuoto? o scrivi il tuo metodo.
jpgeek,

@jpgeek Grazie per il chiarimento, che il problema che stavo avendo nella realizzazione :blank?è specifico di Rails.
Tom,

Perché NoMethodError: undefined method empty? for nil:NilClass, :blank? è meglio di:empty?
Lane,

:blankfunziona meglio di :empty. Perché :emptynon funziona pernil
KBIIX

54

Nel mio progetto utilizzo delete:

cities.delete("")

5
elegante! sfortunatamente non restituisce l'array rimanente, ma piuttosto fluido
Kevin

11
Array.delete è controintuitivo. Funziona come un .delete! () Se esistesse un tale metodo. .Delete () opera direttamente sull'array in modo distruttivo.
scarver2,

41

Quando voglio riordinare un array come questo, utilizzo:

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

Ciò rimuoverà tutti gli elementi vuoti o nulli.


1
In realtà, la risposta di The Tin Man è migliore in quanto rimuoverà anche tutto ciò che corrisponde all'oggetto # vuoto? cioè zero, "", "\ n", "", "\ n \ r", ecc. A differenza della risposta accettata, funzionerà anche senza Rails.
superluminario,

24

Più esplicito

cities.delete_if(&:blank?)

Ciò rimuoverà sia i nilvalori che i valori stringa ( "") vuoti .

Per esempio:

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

cities.delete_if(&:blank?)
# => ["Kathmandu", "Pokhara", "Dharan", "Butwal"]

La rimozione della punteggiatura e l'aggiunta di due punti fornisce "Città: cancella se vuoto": D
clapp

2
vuoto è un metodo rubino o rotaie?
Arnold Roa,

2
@ArnoldRoa È un metodo Rails.
PaulMest

1
cosa succede se c'è uno spazio tra la stringa vuota?
Steven Aguilar,

@StevenAguilar uno spazio è considerato come lunghezza 1 (perché uno spazio è un personaggio). "" .blank? => false
phlegx il

23

Prova questo:

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

4
Questo è liscio e non restituisce ""! Questo è un grande trucco.
Sean Larkin,

2
["Kathmandu", "Pokhara", "", "Dharan", "Butwal"] - [""] - non funzionerà in questo caso
ajahongir,

2.0.0-p247: 001> ["Kathmandu", "Pokhara", "", "Dharan", "Butwal"] - [""] => ["Kathmandu", "Pokhara", "Dharan", "Butwal "] Sembra funzionare per me. Perché pensi che non funzioni?
Raels,

1
@Raels, la stringa vuota in questo caso non è vuota. Ha un solo spazio al suo interno.
Chandranshu,

1
@Chandranshu Mi permetto di dissentire. Ho copiato e incollato il testo in un editor e ho scoperto che non c'era spazio tra le virgolette come hai suggerito. In tal caso, sottrarre ["", ""] funzionerebbe. L'esempio del superluminario è simile e funziona pure. La richiesta originale era di rimuovere "elementi vuoti" e non "elementi vuoti" e l'elemento vuoto di esempio era mostrato nell'OP come "".
Raels,

17

Utilizzare reject:

>> cities = ["Kathmandu", "Pokhara", "", "Dharan", "Butwal"].reject{ |e| e.empty? }
=> ["Kathmandu", "Pokhara", "Dharan", "Butwal"]

13
Oppure, come aNoble osservato in precedenza, reject(&:empty?).
mu è troppo corto

Il simbolo proc è più lento in 1.8.7 rispetto al formato di blocco. È alla pari di quello che ho visto in 1.9.2
Caley Woods

Questo è buono in quanto rimuoverà qualsiasi elemento che corrisponde all'oggetto # vuoto ?, ad es. "\ n", "", zero, "\ n \ n \ n", ecc ...
superluminario

5
nil.empty?pausa booom!
Naveed,

1
@AllenMaxwell @Naveed Se l'array ha zero elementi, precedere il reject(&:empty?)con compactes.[nil, ''].compact.reject(&:empty?)
scarver2

14
cities.reject! { |c| c.blank? }

La ragione per cui si desidera utilizzare blank?sopra empty?è che vuoto riconosce pari a zero, stringhe vuote, e lo spazio bianco. Per esempio:

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

ritornerebbe ancora:

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

E chiamando empty?sul " "tornerà false, che probabilmente si vuole esseretrue .

Nota: blank?è accessibile solo tramite Rails, supporta solo Ruby empty?.


11

Ci sono già molte risposte, ma ecco un altro approccio se sei nel mondo di Rails:

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

4
present?viene da ActiveSupport. Questo non ha un tag Rails e richiedere una gemma in più per un metodo sembra eccessivo.
Michael Kohl,

1
@Naveed, dovresti prefigurarlo con "Se stai usando RoR". Non lo declasserò perché sono ancora informazioni utili per i principianti.
pixelearth

9

Ecco un altro approccio per raggiungere questo obiettivo

possiamo usare presenceconselect

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

cities.select(&:presence)

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

2
Grazie per questo. Avevo alcuni " "elementi nel mio array che non sono stati rimossi con il metodo di rifiuto. Il tuo metodo rimosso nil ""o " "elementi.
iamse7en,

8

Ecco una soluzione se hai tipi misti nel tuo array:

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

Soluzione:

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

Produzione:

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

5

Puoi provare questo

 cities.reject!(&:empty?)

3
forse intendevicities.reject!(&:blank?)
xguox l'

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

cancellare e organizzare sarebbe un'operazione costosa
Naveed,


0

un altro metodo:

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

-2

Aggiornamento con un rigoroso con join&split

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

Il risultato sarà:

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

Nota: questo non funziona con una città con spazi


2
Sembra molto rischioso!
msdundar,

1
Questo fallirà sicuramente se hai città come "New York" o "Naujoji Akmene" :)
Petras L
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.