ทั้งหมดยกเว้นองค์ประกอบสุดท้ายของอาร์เรย์ Ruby


139

สมมติว่าฉันมีอาร์เรย์ทับทิม

a = [1, 2, 3, 4]

ถ้าฉันต้องการทั้งหมดยกเว้นรายการแรกฉันสามารถเขียนa.drop(1)ได้ดีมาก ถ้าฉันต้องการทุกอย่างยกเว้นรายการสุดท้ายฉันก็แค่คิดแบบนี้

a[0..-2]   # or
a[0...-1]

dropแต่ไม่มีของเหล่านี้ดูเหมือนสะอาดเท่าที่ใช้ มีวิธีอื่นในตัวที่ฉันขาดไป


ตามglobalnerdy.com/2008/07/10/…หยดคือ ruby ​​1.9 แทนที่จะเป็น ruby ​​1.8.6
Andrew Grimm

ถ้าฉันต้องใช้คำตอบเหล่านี้ในการวนซ้ำ 1000 ครั้ง .. อันไหนจะชนะ?
Ninad

ในคำอื่น ๆ วิธีการแก้ปัญหาที่ไม่ได้สำรวจอาร์เรย์ภายใต้ประทุน?
Ninad

วิธีอื่น a - ([a.size])
John

คำตอบ:


128

บางที ...

a = t               # => [1, 2, 3, 4]
a.first a.size - 1  # => [1, 2, 3]

หรือ

a.take 3

หรือ

a.first 3

หรือ

a.pop

ซึ่งจะคืนค่าล่าสุดและปล่อยให้อาร์เรย์มีทุกอย่างก่อนหน้านี้

หรือทำให้คอมพิวเตอร์ทำงานสำหรับอาหารเย็น:

a.reverse.drop(1).reverse

หรือ

class Array
  def clip n=1
    take size - n
  end
end
a          # => [1, 2, 3, 4]
a.clip     # => [1, 2, 3]
a = a + a  # => [1, 2, 3, 4, 1, 2, 3, 4]
a.clip 2   # => [1, 2, 3, 4, 1, 2]

5
การเพิ่มวิธีการArrayดูเหมือนจะเป็นวิธีที่ดีที่สุดสำหรับฉัน โครงการส่วนใหญ่จบลงด้วยcore_ext.rbไฟล์ที่มีนามสกุลเล็กน้อยเช่นนี้ ห้องสมุดบางแห่งมีนามสกุลทั้งหมดเช่นนี้ActiveSupportตัวอย่างเช่น
rfunduk

น่าสนใจฉันสงสัยว่ามันเป็นเรื่องธรรมดา ผู้คนคิดอย่างไรกับโหมดบทกวี?
DigitalRoss

5
มีคนส่งclipวิธีนี้ไปยังชุมชน Ruby อย่างไร ผมคิดว่าเรื่องนี้ควรจะอยู่ในที่นั่นและลิงปะเป็นสิ่งที่ผิด
Droogans

7
ฉันชอบa.reverse.drop(1).reverseกลยุทธ์ ;-)
อเล็กซ์

92

จากความอยากรู้ว่าทำไมคุณไม่ชอบa[0...-1]? คุณต้องการรับส่วนแบ่งของอาร์เรย์ดังนั้นตัวดำเนินการส่วนแบ่งจะดูเหมือนตัวเลือกที่ใช้สำนวน

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

class Array
    def drop_last
        self[0...-1]
    end
end

ดูเหมือนว่ามันจะยุ่งเหยิงมากมายเมื่อหล่นสะอาดมาก มันไม่ใช่เรื่องใหญ่ แต่ยากที่จะยืนยันได้ทันทีว่ามันถูกต้อง ฉันชอบชื่อของคุณdrop_lastโดยวิธีการ ...
ปีเตอร์

ฉันชอบที่จะใช้ -1 ที่สวยงามกว่าการใช้. long
Will Nathan

อยากรู้อยากเห็นความหมายของสาม.คืออะไร?
Joshua Pinter

5
... หมายถึงไม่รวมรายการสุดท้าย -1 คือรายการสุดท้าย หากคุณมีจุดสองจุดแล้วมันจะรวมรายการสุดท้ายจุดสามจุดนั้นจะไม่รวมรายการสุดท้าย
ckim

ระวังการใช้โอเปอเรเตอร์สไลซ์ในการรับช่วงอาเรย์: มันอาจกลับมาnil: [][1..-1]-> nil, [][0...-1]->[]
Michael

57

เคล็ดลับเด็ดอีกอย่าง

>> *a, b = [1,2,3]
=> [1, 2, 3]
>> a
=> [1, 2]
>> b
=> 3

นีซไม่ทราบว่ารูบี้มีสิ่งนี้ ดังนั้นa, *b = [1,2,3]ให้เราดูอาร์เรย์ในรถคลาสสิค / cdr แฟชั่น
Nobbynob Littlun

สุจริตฉันไม่จำได้ว่าการเขียนความคิดเห็นที่: D ลบตอนนี้ ...
Petr Bela

Soooo เรียบง่ายและดี ขอบคุณ
microspino

43

หากคุณต้องการดำเนินpop()การกับอาเรย์ (ซึ่งจะส่งผลให้รายการสุดท้ายถูกลบ) แต่คุณสนใจที่จะรับอาเรย์แทนองค์ประกอบที่แตกแล้วคุณสามารถใช้tap(&:pop):

> arr = [1, 2, 3, 4, 5]
> arr.pop
=> 5
> arr
=> [1, 2, 3, 4]
> arr.tap(&:pop)
=> [1, 2, 3]

คำตอบนี้เป็นคำตอบที่เหมาะสมที่สุดสำหรับผู้ใช้รายนี้ การทำงานของกระจกอยู่ใกล้แค่เอื้อมและใช้คำที่ตีความง่าย & รัดกุม
เจอโรม

2
นั่นคือทับทิมที่ลื่นไหล
emptywalls

38

ฉันทำแบบนี้:

my_array[0..-2]

2
มันใช้งานได้ดีมาก ฉันสับสนว่าทำไมมีคำตอบที่ซับซ้อนกว่านี้จำนวนมาก นี่คือการเพิ่มทับทิมใหม่หรือไม่?
Joshua Pinter

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

23

วิธีการเกี่ยวกับการเพิ่มวิธีการปล่อยตัวเองเช่นนี้?

class Array
  def drop(n)
    n < 0 ? self[0...n] : super
  end
end

จากนั้นคุณสามารถใช้ขนาดลบเพื่อลบองค์ประกอบออกจากจุดสิ้นสุดดังนี้:

[1, 2, 3, 4].drop(-1) #=> [1, 2, 3]
[1, 2, 3, 4].drop(-2) #=> [1, 2]

19

a[0...-1]ดูเหมือนจะเป็นวิธีที่ดีที่สุด มีการสร้างไวยากรณ์การแบ่งส่วนข้อมูลของอาร์เรย์เพื่อวัตถุประสงค์นี้ ...

หรือถ้าคุณไม่ทราบการปรับเปลี่ยนอาร์เรย์ในสถานที่ที่คุณสามารถเพียงโทรa.pop:

>> a = [1, 2, 3, 4]
>> a.pop
>> a
=> [1, 2, 3]

คุณยังสามารถกำหนดองค์ประกอบสุดท้ายให้กับตัวแปรเพื่อใช้ในภายหลัง:b = a.pop
Viktor Fonic

12

หากต้องการกำจัดองค์ประกอบสุดท้ายในหนึ่งบรรทัดด้วยการส่งคืนส่วนที่เหลือ

[1, 2, 4, 5, 6].reverse.drop(1).reverse

อย่างจริงจังแม้ว่า

[1,2,3,4][0..-2]
#=> [1,2,3]

11

นี่คือวิธี:

[1,2,3,4,5][0..-1-1]

แต่ขออธิบายวิธีการทำงาน:

a = [1,2,3,4,5]

ตัวอย่างถัดไปจะส่งกลับระเบียนทั้งหมดจากตำแหน่ง 0 ถึงล่าสุด

a[0..-1]
=> [1, 2, 3, 4, 5]

ตัวอย่างถัดไปจะส่งกลับระเบียนจากตำแหน่งที่ 1 ถึงล่าสุด

a[1..-1]
=> [2, 3, 4, 5]

และที่นี่คุณมีสิ่งที่คุณต้องการ ตัวอย่างถัดไปจะส่งกลับระเบียนจากตำแหน่ง 0 ถึงสุดท้าย -1

a[0..-1-1]
=> [1, 2, 3, 4]

1
คุณสามารถเขียนแทน-2 -1-1
bfontaine

คุณสามารถทำได้a[0...-1](สังเกตจุดที่ 3) และรับผลเช่นเดียวกับa[0..-1-1]เพราะจุดที่สามบอกให้แยกองค์ประกอบสิ้นสุด ดูสิ่งนี้สำหรับรายละเอียดเพิ่มเติม
Julien


2

คำตอบ: a.τwτแต่คุณต้องติดตั้งPyperก่อน ...

Pyper intro:คุณรู้จัก Lispy carและcdrส่งคืน "first" และ "rest" ของอาร์เรย์หรือไม่? สำหรับความต้องการเช่นเดียวกับคุณฉันได้เพิ่มกลไก Lispy นี้ มันถูกเรียกว่าpyperและมันช่วยให้คุณสามารถเข้าถึง 2nd, พักจาก 2nd, 3rd, พักผ่อนจาก 3d และสุดท้ายได้ทุกอย่างยกเว้นที่ผ่านมาเป็นต้นซึ่งไม่มากนักที่จะเขียนเกี่ยวกับมันcaar, cadr, cdadarและอื่น ๆ ที่รู้จักจากเสียงกระเพื่อม:

# First, gem install pyper
require 'pyper'
include Pyper
a = %w/lorem ipsum dolor sit amet/
# To avoid confusion with other methods, and also because it resembles a rain gutter,
# Greek letter τ is used to delimit Pyper methods:
aaτ #=> "lorem"
adτ #=> ["ipsum", "dolor", "sit", "amet"]
abτ #=> "ipsum"
aeτ #=> ["dolor", "sit", "amet"]
acτ #=> "dolor" (3rd)
azτ #=> "amet" (last)
ayτ #=> "sit" (2nd from the end)
axτ #=> "dolor" (3rd from the end)

และในที่สุดคำตอบสำหรับคำถามของคุณ:

awτ #=> ["lorem", "ipsum", "dolor", "sit"] (all except last)

มีมากขึ้น:

auτ #=> ["lorem", "ipsum", "dolor"] (all except last 2)
a1τ #=> ["lorem", "ipsum"] (first 2)
a8τ #=> (last 2)
a7τ #=> (last 3)

องค์ประกอบ:

awydτ #=> "olor" (all except 1st letter of the last word of all-except-last array)

นอกจากนี้ยังมีตัวละครมากขึ้นกว่าเพียงแค่คำสั่งa..f, u..zและ0..9สะดุดตาที่สุดmหมายถึงแผนที่:

awmbτ #=> ["o", "p", "o", "i"] (second letters of all-except-last array)

แต่ตัวละครคำสั่งอื่น ๆ นั้นร้อนแรงและไม่ง่ายต่อการใช้งานในตอนนี้


1
ฉันกำลังอ่านสิ่งนี้ในวันที่ 1 เมษายนดังนั้นฉันคิดว่ามันเป็นเรื่องตลก ... ไม่ ไม่รู้ว่ามีสิ่งนี้สำหรับทับทิม :)
Joshua Pinter

1

สิ่งนี้ทำให้อาร์เรย์ใหม่พร้อมองค์ประกอบทั้งหมดยกเว้นองค์ประกอบสุดท้ายของต้นฉบับ:

ary2 = ary.dup
ary2.pop

โปรดทราบว่ามีบางคนแนะนำให้ใช้ #pop หากคุณตกลงที่จะแก้ไขอาเรย์นั้นก็ไม่เป็นไร หากคุณไม่ตกลงกับมันให้ทำซ้ำอาร์เรย์ก่อนเช่นในตัวอย่างนี้


1
มีบางคนแนะนำให้ใช้ #pop หากคุณตกลงที่จะแก้ไขอาเรย์ หากคุณไม่ตกลงกับมันให้ทำซ้ำอาร์เรย์ก่อนเช่นในตัวอย่างนี้
alegscogs

นี่คือความคิดเห็นที่สำคัญ คุณอาจเพิ่มไปยังคำตอบของคุณเช่นกัน เนื่องจาก #pop ไม่มีผลกระทบ (!) ความจริงที่ว่ามันปรับเปลี่ยนอาเรย์ดั้งเดิมอาจหนีผู้คนได้
mjnissim

นี่เป็นวิธีที่ไม่มีประสิทธิภาพถ้าอาร์เรย์มีขนาดใหญ่
juliangonzalez

1

ฉันมักจะพบว่าตัวเองต้องการทั้งหมด แต่องค์ประกอบสุดท้ายของอาร์เรย์ ฉันได้จัดทำฟังก์ชั่นของตัวเองเพื่อให้สามารถอ่านได้มากกว่าโซลูชันอื่น ๆ :

class Array
  def all_but_the_last(n)
    self.first(self.size - n)
  end
end

ตอนนี้คุณสามารถทำสิ่งต่อไปนี้:

arr = ["One", "Two", "Three", "Four", "Five"]
# => ["One", "Two", "Three", "Four", "Five"]

arr.all_but_the_last(1)
# => ["One", "Two", "Three", "Four"]

arr.all_but_the_last(3)
# => ["One", "Two"]

arr.all_but_the_last(5)
# => []

arr.all_but_the_last(6)
# ArgumentError: negative array size

ฉันได้รับอนุญาตโดยเจตนาสำหรับ ArgumentError เพื่อให้ผู้โทรรับผิดชอบวิธีที่พวกเขาใช้วิธีนี้ ฉันชอบที่จะได้ยินความคิดเห็น / วิจารณ์ของวิธีการนี้


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