ฉันจะลบองค์ประกอบหนึ่งจากอาร์เรย์โดยค่า


343

ฉันมีชุดขององค์ประกอบในทับทิม

[2,4,6,3,8]

ฉันต้องการลบองค์ประกอบที่มีค่า 3เช่น

ฉันจะทำอย่างไร


ฉันสงสัยว่าทำไมdelete array.delete(3)ไม่ทำงานภายใน ruby ​​บนตัวควบคุมราง
ImranNaqvi

2
อาจเป็นเพราะactive recordวิธีการdelete
ImranNaqvi

คำตอบ:


481

ฉันคิดว่าฉันคิดออก:

a = [3, 2, 4, 6, 3, 8]
a.delete(3)
#=> 3
a
#=> [2, 4, 6, 8]

189
ผมเองชอบ[1, 2, 3, 4, 5] - [3]ซึ่งผลในการจาก=> [1, 2, 4, 5] irb
เทรวิส

24
เกิดอะไรขึ้นถ้ามี 3 รายการหลายรายการและเราต้องการลบเพียงรายการเดียว? (สิ่งนี้เกี่ยวข้องกับการถามสิ่งนี้ที่นี่อาจจะดีที่สุด)
Navneet

113
เพียงแค่หัวขึ้นว่า. delete () จะคืนค่าที่ถูกลบไม่ใช่อาร์เรย์ที่ถูกแก้ไขที่มีค่าถูกลบออก
Joshua Pinter

23
สิ่งที่ต้องพิจารณาอีกประการหนึ่งคือdeleteการเปลี่ยนแปลงอาเรย์พื้นฐานในขณะที่-สร้างอาเรย์ใหม่ (ที่ส่งคืนให้คุณ) โดยไม่มีค่าที่ถูกลบ ขึ้นอยู่กับกรณีการใช้งานของคุณวิธีการอย่างใดอย่างหนึ่งอาจทำให้รู้สึก
srt32

2
@ user3721428 ลบ (3) ไม่ได้อ้างถึงองค์ประกอบในตำแหน่งที่ 3 แต่แทนที่จะลบองค์ประกอบใด ๆ ที่ตรงกับจำนวนเต็ม 3 มันจะลบเหตุการณ์ที่เกิดขึ้นทั้งหมด 3 และไม่มีอะไรจะทำอย่างไรกับดัชนีอาร์เรย์หรือตำแหน่ง
bkunzi01

226

การยืมตัวจากเทรวิสในความคิดเห็นนี่เป็นคำตอบที่ดีกว่า:

โดยส่วนตัวแล้วฉันชอบ[1, 2, 7, 4, 5] - [7]ซึ่งผลลัพธ์=> [1, 2, 4, 5]มาจากirb

ฉันแก้ไขคำตอบของเขาเพราะเห็นว่า 3 เป็นองค์ประกอบที่สามในอาร์เรย์ตัวอย่างของเขา สิ่งนี้อาจทำให้เกิดความสับสนสำหรับผู้ที่ไม่ทราบว่า 3 อยู่ในตำแหน่งที่ 2 ในอาเรย์


21
ในฐานะที่เป็นจุด srt32 ออกมาในคำตอบที่มีความแตกต่างที่สำคัญที่จะทำให้ระหว่างการใช้และ.delete จะคืนค่าที่ถูกลบออกจากอาเรย์ถ้ามี จะไม่ ดังนั้นจะกลับมาในขณะที่จะกลับมา -.delete-[ 1, 2, 3 ] - [ 2 ][ 1, 3 ][ 1, 2, 3 ].delete( 2 )2
Argus9

5
array - subArrayจะไม่ทำงานสำหรับArray of Arrayแต่array.delete(subArray)จะทำ
Sachin

21
แตกต่างที่สำคัญมากระหว่าง[1,2,3] - [2]และ[1,2,3].delete(2)นั่นคือdeleteวิธีการปรับเปลี่ยนอาร์เรย์เดิมในขณะที่[1,2,3] - [3]สร้างแถวใหม่
Timothy Kovalev

Re subarrays (@ คิดเห็นชินเหนือ) "แน่นอนว่ามันจะ" คุณก็จำเป็นต้องได้รับสัญกรณ์ขวา: [1,2,[2],2,3,4] - [2]ช่วยให้คุณมี[1, [2], 3, 4]แต่จะช่วยให้คุณ[1,2,[2],2,3,4] - [[2]] [1, 2, 2, 3, 4]:-)
Tom Hundt


50

ฉันไม่แน่ใจว่ามีใครระบุสิ่งนี้หรือไม่ แต่ Array.delete () และ - = valueจะลบทุกอินสแตนซ์ของค่าที่ส่งไปให้ภายใน Array ในการลบอินสแตนซ์แรกขององค์ประกอบเฉพาะคุณสามารถทำสิ่งที่ต้องการ

arr = [1,3,2,44,5]
arr.delete_at(arr.index(44))

#=> [1,3,2,5]

อาจมีวิธีที่ง่ายกว่า ฉันไม่ได้บอกว่านี่เป็นวิธีปฏิบัติที่ดีที่สุด แต่เป็นสิ่งที่ควรได้รับการยอมรับ


1
ฉันกำลังมองหาวิธีที่จะทำสิ่งนี้และลบหนึ่งอินสแตนซ์ขององค์ประกอบในกรณีที่ซ้ำกันเท่านั้น
xeroshogun

ฉันคิดว่าคำตอบนี้ผิดเพราะ arr.index () สามารถไปได้nil
windmaomao

32

สมมติว่าคุณต้องการลบ 3 โดยค่าที่หลาย ๆ ที่ในอาเรย์ฉันคิดว่าวิธี ruby ​​ในการทำงานนี้จะใช้เมธอด delete_if:

[2,4,6,3,8,3].delete_if {|x| x == 3 } 

นอกจากนี้คุณยังสามารถใช้ delete_if ในการลบองค์ประกอบในสถานการณ์ของ 'อาร์เรย์ของอาร์เรย์'

หวังว่านี่จะช่วยแก้ไขข้อสงสัยของคุณ


25

ฉันชอบ-=[4]วิธีที่กล่าวถึงในคำตอบอื่น ๆ เพื่อลบองค์ประกอบที่มีค่าเป็น 4

แต่มีวิธีนี้:

irb(main):419:0> [2,4,6,3,8,6].delete_if{|i|i==6}
=> [2, 4, 3, 8]
irb(main):420:0>

พูดถึงบางส่วนใน " การดำเนินการอาร์เรย์พื้นฐาน " หลังจากที่กล่าวถึงmapฟังก์ชั่น


แต่คุณไม่สามารถใช้.delete(6)
Zac

@Zac แน่นอน แต่คำตอบนั้นได้รับการกล่าวถึงแล้ว (เช่นเดียวกับ-=วิธีที่ รัดกุมมากa-=[4]เช่นa=a-[4]. [3,4]-[4]ซึ่งฉันบอกว่าฉันชอบ) แต่ฉันต้องการที่จะพูดถึงวิธีอื่นที่เป็นไปได้
barlop

วิธีนี้ยังมีข้อได้เปรียบในการคืนอาร์เรย์แทนองค์ประกอบที่ถูกลบ
F.Webber



15

นี่คือมาตรฐานบางประการ:

require 'fruity'


class Array          
  def rodrigo_except(*values)
    self - values
  end    

  def niels_except value
    value = value.kind_of?(Array) ? value : [value]
    self - value
  end
end

ARY = [2,4,6,3,8]

compare do
  soziev  { a = ARY.dup; a.delete(3);               a }
  steve   { a = ARY.dup; a -= [3];                  a }
  barlop  { a = ARY.dup; a.delete_if{ |i| i == 3 }; a }
  rodrigo { a = ARY.dup; a.rodrigo_except(3);         }
  niels   { a = ARY.dup; a.niels_except(3);           }
end

# >> Running each test 4096 times. Test will take about 2 seconds.
# >> soziev is similar to barlop
# >> barlop is faster than steve by 2x ± 1.0
# >> steve is faster than rodrigo by 4x ± 1.0
# >> rodrigo is similar to niels

และอีกครั้งด้วยอาร์เรย์ที่ใหญ่กว่าซึ่งประกอบด้วยรายการที่ซ้ำกันมากมาย:

class Array          
  def rodrigo_except(*values)
    self - values
  end    

  def niels_except value
    value = value.kind_of?(Array) ? value : [value]
    self - value
  end
end

ARY = [2,4,6,3,8] * 1000

compare do
  soziev  { a = ARY.dup; a.delete(3);               a }
  steve   { a = ARY.dup; a -= [3];                  a }
  barlop  { a = ARY.dup; a.delete_if{ |i| i == 3 }; a }
  rodrigo { a = ARY.dup; a.rodrigo_except(3);         }
  niels   { a = ARY.dup; a.niels_except(3);           }
end

# >> Running each test 16 times. Test will take about 1 second.
# >> steve is faster than soziev by 30.000000000000004% ± 10.0%
# >> soziev is faster than barlop by 50.0% ± 10.0%
# >> barlop is faster than rodrigo by 3x ± 0.1
# >> rodrigo is similar to niels

และยิ่งใหญ่กว่าด้วยการซ้ำซ้อนมากขึ้น:

class Array          
  def rodrigo_except(*values)
    self - values
  end    

  def niels_except value
    value = value.kind_of?(Array) ? value : [value]
    self - value
  end
end

ARY = [2,4,6,3,8] * 100_000

compare do
  soziev  { a = ARY.dup; a.delete(3);               a }
  steve   { a = ARY.dup; a -= [3];                  a }
  barlop  { a = ARY.dup; a.delete_if{ |i| i == 3 }; a }
  rodrigo { a = ARY.dup; a.rodrigo_except(3);         }
  niels   { a = ARY.dup; a.niels_except(3);           }
end

# >> Running each test once. Test will take about 6 seconds.
# >> steve is similar to soziev
# >> soziev is faster than barlop by 2x ± 0.1
# >> barlop is faster than niels by 3x ± 1.0
# >> niels is similar to rodrigo

7
ดังนั้นสิ่งที่ดีที่สุดคืออะไร? :)
เคอร์บี้

8

ฉันปรับปรุงโซลูชันของ Niels

class Array          
  def except(*values)
    self - values
  end    
end

ตอนนี้คุณสามารถใช้

[1, 2, 3, 4].except(3, 4) # return [1, 2]
[1, 2, 3, 4].except(4)    # return [1, 2, 3]

โซลูชันของคุณไม่ทำงานบนirbคอนโซล 2.2.1 :007 > [1, 2, 3, 4].except(3, 4) NoMethodError: undefined method except for [1, 2, 3, 4]:Array from (irb):7 from /usr/share/rvm/rubies/ruby-2.2.1/bin/irb:11:in <main>
hgsongra

1
class Array; def except(*values); self - values; end; endที่จะประกาศในคณะกรรมการคุณต้องเพิ่มวิธีการอาร์เรย์
Mark Swardstrom

3

คุณยังสามารถปะแก้ลิงได้ ฉันไม่เคยเข้าใจว่าทำไม Ruby มีexceptวิธีการHashแต่ไม่ใช่สำหรับArray:

class Array
  def except value
    value = value.kind_of(Array) ? value : [value]
    self - value
  end
end

ตอนนี้คุณสามารถทำได้:

[1,3,7,"436",354,nil].except(354) #=> [1,3,7,"436",nil]

หรือ:

[1,3,7,"436",354,nil].except([354, 1]) #=> [3,7,"436",nil]

1
คุณไม่จำเป็นต้องvalue.kind_of(Array)ทำการทดสอบ self - Array(value)ใช้เพียงแค่
Sasgorilla

3

ดังนั้นเมื่อคุณมีเหตุการณ์ 3 เหตุการณ์เกิดขึ้นหลายครั้งและคุณต้องการเพียงลบเหตุการณ์แรกที่เกิดขึ้น 3 เหตุการณ์คุณสามารถทำสิ่งต่าง ๆ ดังต่อไปนี้

arr = [2, 4, 6, 3, 8, 10, 3, 12]

arr.delete_at arr.index 3

#This will modify arr as [2, 4, 6, 8, 10, 3, 12] where first occurrence of 3 is deleted. Returns the element deleted. In this case => 3.

3

การกำจัดแบบไม่ทำลายที่เกิดขึ้นครั้งแรก:

a = [2, 4, 6, 3, 8]
n = a.index 3
a.take(n)+a.drop(n+1)

2

หากคุณต้องการให้การดำเนินการลบนี้สามารถโยงได้ดังนั้นคุณสามารถลบบางรายการและทำการผูกมัดการดำเนินการในอาร์เรย์ผลลัพธ์ได้ให้ใช้tap:

[2, 4, 6, 3, 8].tap { |ary| ary.delete(3) }.count #=> 4

1

รวบรวมตัวเลือกต่าง ๆ ทั้งหมดสำหรับการลบในทับทิม

ลบ - ลบองค์ประกอบที่ตรงกันตามค่า หากมีมากกว่าหนึ่งค่าที่ตรงกับมันจะลบทั้งหมด หากคุณไม่สนใจเกี่ยวกับจำนวนที่เกิดขึ้นหรือแน่ใจเกี่ยวกับการเกิดขึ้นครั้งเดียวให้ใช้วิธีนี้

a = [2, 6, 3, 5, 3, 7]
a.delete(3)  # returns 3
puts a       # return [2, 6, 5, 7]

delete_at - ลบองค์ประกอบที่ดัชนีที่กำหนด ถ้าคุณรู้ว่าดัชนีใช้วิธีนี้

# continuing from the above example
a.delete_at(2) # returns 5
puts a         # returns [2, 6, 7]

delete_if - ลบทุกองค์ประกอบที่บล็อกเป็นจริง สิ่งนี้จะแก้ไขอาเรย์ Array เปลี่ยนไปทันทีที่บล็อคถูกเรียก

b = [1, 2, 5, 4, 9, 10, 11]
b.delete_if {|n| n >= 10}.  # returns [1, 2, 5, 4, 9]

ปฏิเสธ - นี่จะส่งคืนอาร์เรย์ใหม่ที่มีองค์ประกอบซึ่งบล็อกที่กำหนดเป็นเท็จ การสั่งซื้อจะได้รับการปรับปรุงด้วยสิ่งนี้

c = [1, 2, 5, 4, 9, 10, 11]
c.reject {|n| n >= 10}.  # returns [1, 2, 5, 4, 9]

ปฏิเสธ! - เหมือนกับ delete_if delete_ifอาร์เรย์อาจไม่เปลี่ยนแปลงทันทีในขณะที่บล็อกถูกเรียก

หากคุณต้องการลบค่าหลายค่าจากอาร์เรย์ตัวเลือกที่ดีที่สุดคือการร้อง

a = [2, 3, 7, 4, 6, 21, 13]
b = [7, 21]
a = a - b    # a - [2, 3, 4, 6, 13]
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.