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?

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


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

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

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

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.


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

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

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

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


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?

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

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]

5

Sie können dies versuchen

 cities.reject!(&:empty?)

3
Vielleicht cities.reject!(&:blank?)
meintest

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

Löschen und Anordnen wäre eine kostspielige Operation
Naveed


0

eine andere Methode:

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

-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


2
Sieht sehr riskant aus!
Msdundar

1
Dies wird definitiv scheitern, wenn Sie eine Stadt wie "New York" oder "Naujoji Akmene" haben :)
Petras L
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.