Jak usunąć puste elementy z tablicy?


284

Mam następującą tablicę

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

Chcę usunąć puste elementy z tablicy i chcę następujący wynik:

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

Czy jest jakaś metoda compact, która zrobi to bez pętli?

Odpowiedzi:


501

Jest na to wiele sposobów, jednym z nich jest reject

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

Możesz również użyć reject!, który zmodyfikuje citiesw miejscu. Zwróci albo citieswartość zwrotną, jeśli coś odrzuci, albo nilnie zostanie odrzucony. Może to być problem, jeśli nie jesteś ostrożny (dzięki ninja08 za wskazanie tego w komentarzach).


227
Lub jeśli wolisz bardziej kompaktowycities.reject!(&:empty?)
aNoble

53
hm, czemu nie cities.reject!(&:blank?)? empty?jest na tablice
Nico,

27
@Nico blank?jest dostępne tylko za pośrednictwem ActiveSupport. Standardowy Ruby używa String#empty?: ruby-doc.org/core-1.9.3/String.html#method-i-empty-3F
Michael Kohl

24
rejectjest lepszy niż reject!dlatego , że [].reject!(&:empty?)wraca nil, [].reject(&:empty?)wraca[]
konyak

17
uważaj z odrzuceniem !. odrzucać! zwróci zero, jeśli nie zostaną wprowadzone żadne zmiany w tablicy. Jeśli chcesz zwrócić tablicę, gdy nie dokonano żadnych zmian, po prostu użyj odrzucenia bez huku.
Nick Res,

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

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

5
Wolałbym użyć .reject (&: blank?), Aby uniknąć również wartości zerowych
ran632

4
@RanGalili blank?to dobry wybór, ale jest to railsmetoda, a to pytanie dotyczy zwykłegoruby
Swaps

83

Oto, co działa dla mnie:

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

wynik:

[1, 2, "hello"]

Na Ruby 2.3.1 dostaję NoMethodError: "niezdefiniowana metoda` pusta? ' dla 1: Fixnum ”próbuje to wykonać.
Tom

1
@Tom puste? jest metodą specyficzną dla Railsów. Nie istnieje w Array dla zwykłego rubinu. Będziesz musiał użyć pustego? lub napisz własną metodę.
jpgeek

@jpgeek Dziękuję za wyjaśnienie, że miałem problem z uświadomieniem sobie, że :blank?jest specyficzny dla Railsów.
Tom

Ponieważ NoMethodError: undefined method empty? for nil:NilClass, :blank? jest lepsze niż:empty?
Lane

:blankdziała lepiej niż :empty. Ponieważ :emptynie działa dlanil
KBIIX

54

W moim projekcie używam delete:

cities.delete("")

5
elegancki! niestety nie zwraca pozostałej tablicy, ale całkiem sprytnie
Kevin

11
Array.delete jest sprzeczny z intuicją. Działa jak .delete! (), Jeśli taka metoda istnieje. .Delete () działa destrukcyjnie bezpośrednio na macierz.
scarver2

41

Kiedy chcę uporządkować tablicę taką jak ta, używam:

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

Spowoduje to usunięcie wszystkich pustych lub zerowych elementów.


1
Właściwie odpowiedź Tin Mana jest lepsza, ponieważ usunie także wszystko, co pasuje do Object # puste? tj. zero, „”, „\ n”, „”, „\ n \ r” itd. W przeciwieństwie do przyjętej odpowiedzi, będzie również działać bez Railsów.
superluminarny

24

Najbardziej wyraźne

cities.delete_if(&:blank?)

Spowoduje to usunięcie zarówno nilwartości, jak i pustych wartości string ( "").

Na przykład:

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

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

Usunięcie interpunkcji i dodanie dwukropka daje „Miasta: usuń, jeśli puste”: D
clapp

2
puste to metoda ruby ​​lub szyn?
Arnold Roa

2
@ArnoldRoa Jest to metoda Railsowa.
PaulMest

1
co jeśli pomiędzy pustym ciągiem jest spacja?
Steven Aguilar,

@StevenAguilar spację uważa się za długość 1 (ponieważ spacja jest znakiem). „” .blank? => false
flegma

23

Spróbuj tego:

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

4
Jest zręczny i nie zwraca „”! To świetna sztuczka lil.
Sean Larkin,

2
[„Kathmandu”, „Pokhara”, „”, „Dharan”, „Butwal”] - [„”] - nie zadziała w tym przypadku
ajahongir,

2.0.0-p247: 001> [„Kathmandu”, „Pokhara”, „”, „Dharan”, „Butwal”] - [„”]] => [„Kathmandu”, „Pokhara”, „Dharan”, „Butwal „] Wydaje się pracować dla mnie. Jak myślisz, dlaczego to nie działa?
Raels

1
@Raels, pusty ciąg w tym przypadku nie jest pusty. Ma w sobie jedną przestrzeń.
Chandranshu,

1
@Chandranshu Zaczynam się różnić. Skopiowałem i wkleiłem tekst do edytora i stwierdziłem, że między cytatami nie ma spacji, jak sugerowałeś. Gdyby tak było, odejmowanie [””, „”] działałoby. przykład superluminarium jest podobny i działa również. Pierwotnym żądaniem było usunięcie „pustych elementów”, a nie „pustych elementów”, a przykładowy pusty element został pokazany w OP jako „”.
Raels

17

Użyj reject:

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

13
Albo, jak zauważono aNoble powyżej reject(&:empty?).
mu jest za krótki

Symbol proc jest wolniejszy w 1.8.7 niż format blokowy. Jest na równi z tym, co widziałem w 1.9.2
Caley Woods

Jest to dobre, ponieważ usunie każdy element pasujący do obiektu # pusty ?, np. „\ n”, „”, zero, „\ n \ n \ n” itd.
superluminarium

5
nil.empty?przerwa w grze!
Naveed,

1
@AllenMaxwell @Naveed Jeśli tablica ma elementy zerowa, poprzedzać reject(&:empty?)z compactnp[nil, ''].compact.reject(&:empty?)
scarver2

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

Powodem chcesz używać blank?na empty?to, że puste rozpoznaje zerowa, pustych strun i białą przestrzeń. Na przykład:

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

nadal wróciłby:

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

I powołanie empty?na " "zwrot ten false, który prawdopodobnie ma być true.

Uwaga: blank?jest dostępny tylko przez Railsy, ​​Ruby obsługuje tylko empty?.


11

Jest już wiele odpowiedzi, ale oto inne podejście, jeśli jesteś w świecie Railsów:

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

4
present?pochodzi z ActiveSupport. Nie ma tagu Rails, a wymaganie dodatkowego klejnotu dla jednej metody wydaje się nadmierne.
Michael Kohl,

1
@Naveed, powinieneś poprzedzić to słowem „Jeśli używasz RoR”. Nie będę go głosować, ponieważ nadal jest to przydatna informacja dla początkujących.
pixelearth

9

Oto jeszcze jedno podejście do osiągnięcia tego celu

możemy używać presencezselect

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

cities.select(&:presence)

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

2
Dziękuję Ci za to. Miałem kilka " "elementów w mojej tablicy, które nie zostały usunięte za pomocą metody odrzucania. Twoja metoda została usunięta nil ""lub " "przedmioty.
iamse7en

8

Oto rozwiązanie, jeśli masz mieszane typy w tablicy:

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

Rozwiązanie:

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

Wynik:

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


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

usuwanie i aranżacja byłoby kosztowną operacją
Naveed,


0

inna metoda:

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

-2

Aktualizacja z surowa join&split

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

Wynik będzie:

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

Zauważ, że: to nie działa z miastem ze spacjami


2
Wygląda bardzo ryzykownie!
msdundar

1
To na pewno się nie powiedzie, jeśli masz takie miasto jak „Nowy Jork” lub „Naujoji Akmene” :)
Petras L
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.