Wie entferne ich leere Elemente aus einem Array?

284

Ich habe das folgende Array

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

Ich möchte leere Elemente aus dem Array entfernen und das folgende Ergebnis erzielen:

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

Gibt es eine compactsolche Methode , die es ohne Schleifen schafft?

ashisrai_
quelle

Antworten:

501

Es gibt viele Möglichkeiten, dies zu tun reject

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

Sie können auch verwenden reject!, die citiesan Ort und Stelle geändert wird . Es wird entweder citiesals Rückgabewert zurückgegeben, wenn etwas abgelehnt wurde oder nilwenn keine Ablehnungen vorgenommen wurden. Das kann ein Problem sein, wenn Sie nicht aufpassen (danke an ninja08 für den Hinweis in den Kommentaren).

Matt Greer
quelle
227
Oder wenn Sie kompakter bevorzugencities.reject!(&:empty?)
aNoble
53
hm, warum nicht cities.reject!(&:blank?)? empty?ist für Arrays
Nico
27
@Nico blank?ist nur über verfügbar ActiveSupport. Standard Ruby verwendet String#empty?: ruby-doc.org/core-1.9.3/String.html#method-i-empty-3F
Michael Kohl
24
rejectist besser als reject!weil [].reject!(&:empty?)zurückkehrt nil, [].reject(&:empty?)zurückkehrt[]
konyak
17
Vorsicht mit Ablehnung!. ablehnen! gibt nil zurück, wenn keine Änderungen am Array vorgenommen werden. Wenn Sie das Array zurückgeben möchten, wenn keine Änderungen vorgenommen wurden, verwenden Sie einfach "Reject" ohne Knall.
Nick Res
164
1.9.3p194 :001 > ["", "A", "B", "C", ""].reject(&:empty?)

=> ["A", "B", "C"]
user2010324
quelle
5
Ich würde es vorziehen, .reject (&: blank?) Zu verwenden, um auch keine Werte zu vermeiden
ran632
4
@ RanGalili blank?ist eine gute Wahl, aber es ist eine railsMethode, und diese Frage bezieht sich auf die Ebeneruby
Swaps
83

Folgendes funktioniert bei mir:

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

Ausgabe:

[1, 2, "hello"]
kimerseen
quelle
Unter Ruby 2.3.1 erhalte ich NoMethodError: "undefinierte Methode` leer? ' für 1: Fixnum "versucht dies auszuführen.
Tom
1
@ Tom leer? ist eine Rails-spezifische Methode. Existiert nicht auf Array für einfachen Rubin. Sie müssen leer verwenden? oder schreiben Sie Ihre eigene Methode.
Jpgeek
@jpgeek Danke für die Klarstellung, das war das Problem, das ich bei der Realisierung hatte, :blank?ist Rails-spezifisch.
Tom
Da NoMethodError: undefined method empty? for nil:NilClass, :blank? ist besser als:empty?
Lane
:blankfunktioniert besser als :empty. Weil :emptyfunktioniert nicht fürnil
KBIIX
54

In meinem Projekt verwende ich delete:

cities.delete("")
esio
quelle
5
elegant! Leider wird das verbleibende Array nicht zurückgegeben, aber ziemlich schick
Kevin
11
Das Array.delete ist nicht intuitiv. Es funktioniert wie ein .delete! (), Wenn eine solche Methode existiert. Die .delete () arbeitet destruktiv direkt auf dem Array.
Scarver2
41

Wenn ich ein Array wie dieses aufräumen möchte, verwende ich:

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

Dadurch werden alle leeren oder Null-Elemente entfernt.

überleuchtet
quelle
1
Tatsächlich ist die Antwort von The Tin Man besser, da dadurch auch alles entfernt wird, was mit Objekt # leer übereinstimmt. dh null, "", "\ n", "", "\ n \ r" usw. Im Gegensatz zur akzeptierten Antwort funktioniert es auch ohne Rails.
Superluminary
24

Am explizitesten

cities.delete_if(&:blank?)

Dadurch werden sowohl nilWerte als auch leere string ( "") -Werte entfernt.

Beispielsweise:

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

cities.delete_if(&:blank?)
# => ["Kathmandu", "Pokhara", "Dharan", "Butwal"]
Schleim
quelle
Das Entfernen der Interpunktion und das Hinzufügen eines Doppelpunkts ergibt "Städte: Löschen, wenn leer": D
clapp
2
leer ist eine Rubin- oder Schienenmethode?
Arnold Roa
2
@ArnoldRoa Es ist eine Rails-Methode.
PaulMest
1
Was ist, wenn zwischen der leeren Zeichenfolge ein Leerzeichen steht?
Steven Aguilar
@StevenAguilar Ein Leerzeichen wird als Länge 1 betrachtet (da ein Leerzeichen ein Zeichen ist). "" .blank? => false
Phlegx
23

Versuche dies:

puts ["Kathmandu", "Pokhara", "", "Dharan", "Butwal"] - [""]
Raels
quelle
4
Dies ist glatt und gibt nicht "" zurück! Dies ist ein großartiger kleiner Trick.
Sean Larkin
2
["Kathmandu", "Pokhara", "", "Dharan", "Butwal"] - [""] - wird in diesem Fall nicht funktionieren
Ajahongir
2.0.0-p247: 001> ["Kathmandu", "Pokhara", "", "Dharan", "Butwal"] - [""] => ["Kathmandu", "Pokhara", "Dharan", "Butwal" "] Scheint für mich zu arbeiten. Warum denkst du, funktioniert es nicht?
Raels
1
@ Raels, die leere Zeichenfolge ist in diesem Fall nicht leer. Es hat einen einzigen Raum in sich.
Chandranshu
1
@Chandranshu Ich bitte, mich zu unterscheiden. Ich habe den Text kopiert und in einen Editor eingefügt und festgestellt, dass zwischen den Anführungszeichen kein Platz ist, wie Sie vorgeschlagen haben. Wenn ja, würde das Subtrahieren von ["", ""] funktionieren. Das Beispiel von superluminary ist ähnlich und funktioniert auch. Die ursprüngliche Anforderung bestand darin, "leere Elemente" und nicht "leere Elemente" zu entfernen, und das Beispiel für ein leeres Element wurde im OP als "" angezeigt.
Raels
17

Verwendung reject:

>> cities = ["Kathmandu", "Pokhara", "", "Dharan", "Butwal"].reject{ |e| e.empty? }
=> ["Kathmandu", "Pokhara", "Dharan", "Butwal"]
der Blechmann
quelle
13
Oder, wie oben erwähnt reject(&:empty?).
Mu ist zu kurz
Das zu verarbeitende Symbol ist in 1.8.7 langsamer als das Blockformat. Es ist auf dem Niveau von dem, was ich in 1.9.2
Caley Woods
Dies ist gut, da dadurch jedes Element entfernt wird, das mit Objekt # leer? Entspricht, z. "\ n", "", nil, "\ n \ n \ n" usw.
Superluminary
5
nil.empty?Booom Pause!
Naveed
1
@AllenMaxwell @Naveed Wenn Ihr Array keine Elemente enthält, gehen Sie dem reject(&:empty?)mit compacteg[nil, ''].compact.reject(&:empty?)
scarver2
14
cities.reject! { |c| c.blank? }

Der Grund , den Sie verwenden möchten blank?über empty?ist , dass leer erkennt null, leere Strings und weißen Raum. Zum Beispiel:

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

würde immer noch zurückkehren:

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

Und ruft empty?auf " "Willen Rückkehr false, die Sie wahrscheinlich sein wollen true.

Hinweis: blank?Zugriff nur über Rails, Ruby unterstützt nur empty?.

Colton Fent
quelle
11

Es gibt bereits viele Antworten, aber hier ist ein anderer Ansatz, wenn Sie in der Rails-Welt sind:

 cities = ["Kathmandu", "Pokhara", "", "Dharan", "Butwal"].select &:present?
Naveed
quelle
4
present?kommt von ActiveSupport. Dies hat ein No-Rails-Tag und das Erfordernis eines zusätzlichen Edelsteins für eine Methode scheint übertrieben.
Michael Kohl
1
@Naveed, Sie sollten dies mit "Wenn Sie RoR verwenden" voranstellen. Ich werde es nicht ablehnen, da es immer noch nützliche Informationen für Anfänger sind.
Pixelearth
9

Hier ist ein weiterer Ansatz, um dies zu erreichen

wir können presencemit verwendenselect

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

cities.select(&:presence)

["Kathmandu", "Pokhara", "Dharan", "Butwal"]
Sampat Badhe
quelle
2
Danke dafür. Ich hatte einige " "Elemente in meinem Array, die mit der Ablehnungsmethode nicht entfernt wurden. Ihre Methode entfernt nil ""oder " "Elemente.
iamse7en
8

Hier ist eine Lösung, wenn Sie gemischte Typen in Ihrem Array haben:

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

Lösung:

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

Ausgabe:

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

Sie können dies versuchen

 cities.reject!(&:empty?)
Anusha
quelle
3
Vielleicht cities.reject!(&:blank?)
meintest
2
 cities = ["Kathmandu", "Pokhara", "", "Dharan", "Butwal"].delete_if {|c| c.empty? } 
suren
quelle
Löschen und Anordnen wäre eine kostspielige Operation
Naveed
2

Kürzester Weg cities.select(&:present?)

Javier Segovia
quelle
0

eine andere Methode:

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

Update mit einem strengen mit join&split

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

Ergebnis wird sein:

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

Beachten Sie Folgendes: Dies funktioniert nicht mit einer Stadt mit Leerzeichen

Hieu Pham
quelle
2
Sieht sehr riskant aus!
Msdundar
1
Dies wird definitiv scheitern, wenn Sie eine Stadt wie "New York" oder "Naujoji Akmene" haben :)
Petras L