ฉันจะลบองค์ประกอบว่างออกจากอาร์เรย์ได้อย่างไร


284

ฉันมีอาเรย์ต่อไปนี้

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

ฉันต้องการลบองค์ประกอบว่างเปล่าออกจากอาร์เรย์และต้องการผลลัพธ์ต่อไปนี้:

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

มีวิธีการเช่นcompactนี้ไหมที่จะทำโดยไม่ต้องวนซ้ำ?

คำตอบ:


501

มีหลายวิธีในการทำเช่นนี้หนึ่งคือ reject

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

นอกจากนี้คุณยังสามารถใช้reject!ซึ่งจะแก้ไขcitiesในสถานที่ มันจะส่งคืนcitiesเป็นค่าส่งคืนหากปฏิเสธบางสิ่งหรือnilหากไม่มีการปฏิเสธ นั่นอาจเป็น gotcha ถ้าคุณไม่ระวัง (ขอบคุณ ninja08 ที่ชี้เรื่องนี้ในความคิดเห็น)


227
หรือถ้าคุณต้องการกะทัดรัดมากกว่านี้cities.reject!(&:empty?)
aNoble

53
hm ทำไมไม่cities.reject!(&:blank?)? empty?สำหรับอาร์เรย์
Nico

27
@Nico เป็นเพียงผ่านใช้ได้blank? ActiveSupportทับทิมมาตรฐานใช้String#empty?: ruby-doc.org/core-1.9.3/String.html#method-i-empty-3F
Michael Kohl

24
rejectจะดีกว่าreject!เพราะ[].reject!(&:empty?)ผลตอบแทนnil, [].reject(&:empty?)ผลตอบแทน[]
Konyak

17
ระวังด้วยปฏิเสธ! ปฏิเสธ! จะคืนค่าศูนย์หากไม่มีการเปลี่ยนแปลงใด ๆ ในอาเรย์ ถ้าคุณต้องการคืนค่าอาเรย์เมื่อไม่มีการเปลี่ยนแปลงให้ใช้การปฏิเสธโดยไม่ใช้ปัง
Nick Res

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

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

5
ฉันต้องการใช้ .reject (&: blank?) เพื่อหลีกเลี่ยงค่าศูนย์เช่นกัน
ran632

4
@RanGalili blank?เป็นตัวเลือกที่ดี แต่มันเป็นrailsวิธีการและคำถามนี้เกี่ยวกับที่ราบruby
22416 Swaps

83

นี่คือสิ่งที่ได้ผลสำหรับฉัน:

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

เอาท์พุท:

[1, 2, "hello"]

ใน Ruby 2.3.1 ฉันได้รับ NoMethodError: "ไม่ได้กำหนดเมธอด` เปล่า? ' for 1: Fixnum "พยายามดำเนินการนี้
ทอม

1
@ ว่างเปล่า? เป็นวิธีเฉพาะของ Rails ไม่มีอยู่ใน Array สำหรับทับทิมธรรมดา คุณจะต้องใช้ที่ว่างเปล่า? หรือเขียนวิธีการของคุณเอง
jpgeek

@jpgeek ขอบคุณสำหรับความกระจ่างนั่นเป็นปัญหาที่ฉันมีในการตระหนักถึง:blank?เป็นเฉพาะทางรถไฟ
ทอม

เพราะNoMethodError: undefined method empty? for nil:NilClass, :blank? ดีกว่า:empty?
เลน

:blank:emptyทำงานได้ดีกว่า เพราะ:emptyใช้งานไม่ได้nil
KBIIX

54

ในโครงการของฉันฉันใช้delete:

cities.delete("")

5
! สง่างาม น่าเสียดายที่ไม่ได้คืนค่าอาเรย์ที่เหลือ แต่มันลื่นไหล
Kevin

11
Array.delete นั้นตอบโต้ได้ง่าย มันทำงานเหมือน. delete! () หากมีวิธีการดังกล่าวอยู่ .delete () ทำงานโดยตรงกับอาเรย์ในลักษณะการทำลายล้าง
scarver2

41

เมื่อฉันต้องการจัดระเบียบอาร์เรย์เช่นนี้ฉันใช้:

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

สิ่งนี้จะลบองค์ประกอบว่างหรือไม่มีทั้งหมด


1
ที่จริงแล้วคำตอบของ Tin Man นั้นดีกว่าเพราะมันจะลบอะไรที่ตรงกับ Object # blank? เช่นไม่มี "", "\ n", "", "\ n \ r" เป็นต้นซึ่งแตกต่างจากคำตอบที่ยอมรับมันจะทำงานได้โดยไม่ต้องใช้ Rails
superluminary

24

ชัดเจนที่สุด

cities.delete_if(&:blank?)

สิ่งนี้จะลบทั้งnilค่าและค่าสตริงว่าง ( "")

ตัวอย่างเช่น:

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

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

การลบเครื่องหมายวรรคตอนและการเพิ่มเครื่องหมายโคลอนจะให้ "เมือง: ลบหากว่าง": D
clapp

2
ว่างเปล่าเป็นวิธีทับทิมหรือราง?
Arnold Roa

2
@ArnoldRoa มันเป็นวิธีการทางรถไฟ
PaulMest

1
ถ้ามีช่องว่างระหว่างสตริงว่าง
Steven Aguilar

@StevenAguilar เว้นวรรคถือเป็นความยาว 1 (เนื่องจากช่องว่างเป็นอักขระ) "" ว่างเปล่า => false
phlegx

23

ลองสิ่งนี้:

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

4
นี่คือเนียนและจะไม่กลับ ""! นี่คือเคล็ดลับ lil ที่ดี
Sean Larkin

2
["กาฐมา ณ ฑุ", "Pokhara", "", "Dharan", "Butwal"] - [""] - จะไม่ทำงานในกรณีนี้
ajahongir

2.0.0-p247: 001> ["กาฐมา ณ ฑุ", "Pokhara", "", "Dharan", "Butwal"] - [""] => ["กาฐมา ณ ฑุ", "Pokhara", "Dharan", "Butwal "] ดูเหมือนว่าจะทำงานให้ฉัน ทำไมคุณคิดว่ามันใช้งานไม่ได้
Raels

1
@Raels สตริงว่างในกรณีนี้ไม่ว่างเปล่า มันมีพื้นที่เดียวภายใน
Chandranshu

1
@Chandranshu ฉันขอแตกต่างกัน ฉันคัดลอกและวางข้อความลงในโปรแกรมแก้ไขและพบว่าไม่มีช่องว่างระหว่างคำพูดตามที่คุณแนะนำ หากมีแล้วการลบ ["", ""] จะใช้งานได้ ตัวอย่างของ superluminary นั้นคล้ายกันและใช้ได้เช่นกัน คำขอเดิมคือการลบองค์ประกอบ "ว่างเปล่า" ไม่ใช่ "องค์ประกอบที่เป็นช่องว่าง" และตัวอย่างองค์ประกอบที่ว่างเปล่าถูกแสดงใน OP เป็น ""
Raels

17

การใช้reject:

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

13
หรือเป็น aNoble reject(&:empty?)ระบุไว้ข้างต้น
mu สั้นเกินไป

Symbol to proc ช้ากว่า 1.8.7 ในรูปแบบบล็อก มันอยู่ห่างจากสิ่งที่ฉันเคยเห็นใน 1.9.2
Caley Woods

สิ่งนี้ดีเพราะจะลบองค์ประกอบใด ๆ ที่ตรงกับ Object # empty? "\ n", "", ไม่มี, "\ n \ n \ n", ฯลฯ ...
superluminary

5
nil.empty?ทำลาย Booom!
Naveed

1
@AllenMaxwell @Naveed หากอาร์เรย์ของคุณมีองค์ประกอบว่างให้นำหน้าreject(&:empty?)ด้วยcompactเช่น[nil, ''].compact.reject(&:empty?)
scarver2 2

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

เหตุผลที่คุณต้องการใช้blank?มากกว่าempty?นั้นคือช่องว่างรับรู้ว่าไม่มีสตริงว่างและช่องว่าง ตัวอย่างเช่น:

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

จะยังคงกลับมา:

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

และเรียกempty?ได้ที่" "จะกลับมาซึ่งคุณอาจต้องการที่จะfalsetrue

หมายเหตุ: สามารถเข้าถึงได้เฉพาะผ่านทางรถไฟทับทิมสนับสนุนเท่านั้นblank?empty?


11

มีคำตอบมากมายอยู่แล้ว แต่นี่เป็นอีกแนวทางหนึ่งหากคุณอยู่ในโลกของ Rails:

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

4
present?ActiveSupportมาจาก นี่คือแท็กไม่มี Rails และต้องการอัญมณีพิเศษสำหรับวิธีการหนึ่งที่ดูเหมือนว่ามากเกินไป
Michael Kohl

1
@ ไม่มีคุณควรนำหน้าด้วย "ถ้าคุณใช้ RoR" ฉันจะไม่ลงคะแนนเพราะยังคงมีข้อมูลที่เป็นประโยชน์สำหรับผู้เริ่มต้น
pixelearth

9

นี่เป็นอีกวิธีการหนึ่งในการบรรลุเป้าหมายนี้

เราสามารถใช้presenceกับselect

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

cities.select(&:presence)

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

2
ขอบคุณสำหรับสิ่งนี้. ฉันมี" "องค์ประกอบบางอย่างในอาร์เรย์ของฉันที่ไม่ได้ถูกลบด้วยวิธีการปฏิเสธ วิธีการของคุณถูกลบnil ""หรือ" "รายการ
iamse7en

8

นี่คือทางออกถ้าคุณมีประเภทผสมในอาร์เรย์ของคุณ:

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

สารละลาย:

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

เอาท์พุท:

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


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

การลบและการจัดเรียงจะเป็นการดำเนินการที่มีค่าใช้จ่าย
Naveed



-2

อัปเดตด้วยเข้มงวดกับjoin&split

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

ผลลัพธ์จะเป็น:

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

โปรดทราบว่า: วิธีนี้ใช้ไม่ได้กับเมืองที่มีช่องว่าง


2
ดูมีความเสี่ยงมาก!
msdundar

1
สิ่งนี้จะล้มเหลวอย่างแน่นอนหากคุณมีเมืองเช่น "New York" หรือ "Naujoji Akmene" :)
Petras L
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.