จะส่งคืนส่วนหนึ่งของอาร์เรย์ใน Ruby ได้อย่างไร?


125

ด้วยรายการใน Python ฉันสามารถส่งคืนส่วนหนึ่งโดยใช้รหัสต่อไปนี้:

foo = [1,2,3,4,5,6]
bar = [10,20,30,40,50,60]
half = len(foo) / 2
foobar = foo[:half] + bar[half:]

เนื่องจาก Ruby ทำทุกอย่างในอาร์เรย์ฉันจึงสงสัยว่ามีบางอย่างที่คล้ายกันหรือไม่

คำตอบ:


192

ใช่ Ruby มีไวยากรณ์การแบ่งอาร์เรย์ที่คล้ายกันมากกับ Python นี่คือriเอกสารสำหรับวิธีดัชนีอาร์เรย์:

--------------------------------------------------------------- Array#[]
     array[index]                -> obj      or nil
     array[start, length]        -> an_array or nil
     array[range]                -> an_array or nil
     array.slice(index)          -> obj      or nil
     array.slice(start, length)  -> an_array or nil
     array.slice(range)          -> an_array or nil
------------------------------------------------------------------------
     Element Reference---Returns the element at index, or returns a 
     subarray starting at start and continuing for length elements, or 
     returns a subarray specified by range. Negative indices count 
     backward from the end of the array (-1 is the last element). 
     Returns nil if the index (or starting index) are out of range.

        a = [ "a", "b", "c", "d", "e" ]
        a[2] +  a[0] + a[1]    #=> "cab"
        a[6]                   #=> nil
        a[1, 2]                #=> [ "b", "c" ]
        a[1..3]                #=> [ "b", "c", "d" ]
        a[4..7]                #=> [ "e" ]
        a[6..10]               #=> nil
        a[-3, 3]               #=> [ "c", "d", "e" ]
        # special cases
        a[5]                   #=> nil
        a[6, 1]                #=> nil
        a[5, 1]                #=> []
        a[5..10]               #=> []

5
เหตุใด [5, 1] ​​จึงแตกต่างจาก [6, 1]
dertoni


25
a[2..-1]ที่จะได้รับจากองค์ประกอบที่ 3 ไปยังองค์ประกอบสุดท้าย a[2...-1]ที่จะได้รับจากองค์ประกอบที่ 3 ถึงองค์ประกอบสุดท้ายที่สอง
Clever Programmer

1
@Rafeh ไชโยสงสัยว่าขยะนี้ทำงานอย่างไร -1 ใช้เคล็ดลับ
Ben Sinclair

ไวยากรณ์ของ @CleverProgrammer ใกล้เคียงกับ Python มากกว่าคำตอบที่ยอมรับ ฉันชอบ Ruby แต่ต้องบอกว่าไวยากรณ์ของ Python นั้นสั้นและชัดเจนกว่า เป็นโบนัสสามารถระบุขั้นตอน:range(10)[:5:-1]
Eric Duminil


17

คุณสามารถใช้slice ()สำหรับสิ่งนี้:

>> foo = [1,2,3,4,5,6]
=> [1, 2, 3, 4, 5, 6]
>> bar = [10,20,30,40,50,60]
=> [10, 20, 30, 40, 50, 60]
>> half = foo.length / 2
=> 3
>> foobar = foo.slice(0, half) + bar.slice(half, foo.length)
=> [1, 2, 3, 40, 50, 60]

อย่างไรก็ตามเพื่อความรู้ที่ดีที่สุดของฉัน Python "รายการ" เป็นเพียงการใช้อาร์เรย์ที่เติบโตแบบไดนามิกอย่างมีประสิทธิภาพ การแทรกที่จุดเริ่มต้นอยู่ใน O (n) การแทรกที่ส่วนท้ายจะถูกตัดจำหน่าย O (1) การเข้าถึงแบบสุ่มคือ O (1)


คุณต้องการใช้บาร์อาร์เรย์ในส่วนที่สองหรือไม่?
ซามูเอล

FYI: slice!()ไม่ได้แก้ไขอาร์เรย์แทน แต่จะเป็น "ลบองค์ประกอบที่ได้รับจากดัชนี (เลือกได้ตามความยาวองค์ประกอบ) หรือตามช่วง" ต่อruby-doc.org/core-2.2.3/Array.html#method-i-slice-21
Joshua Pinter

7

อีกวิธีหนึ่งคือการใช้วิธีช่วง

foo = [1,2,3,4,5,6]
bar = [10,20,30,40,50,60]
a = foo[0...3]
b = bar[3...6]

print a + b 
=> [1, 2, 3, 40, 50 , 60]

3

Ruby 2.6 ช่วงเริ่มต้น / ไม่มีที่สิ้นสุด

(..1)
# or
(...1)

(1..)
# or
(1...)

[1,2,3,4,5,6][..3]
=> [1, 2, 3, 4]

[1,2,3,4,5,6][...3]
 => [1, 2, 3]

ROLES = %w[superadmin manager admin contact user]
ROLES[ROLES.index('admin')..]
=> ["admin", "contact", "user"]

2

ฉันชอบช่วงสำหรับสิ่งนี้:

def first_half(list)
  list[0...(list.length / 2)]
end

def last_half(list)
  list[(list.length / 2)..list.length]
end

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

ตัวอย่างข้างต้นจะใส่องค์ประกอบตรงกลางในช่วงครึ่งหลังอย่างสม่ำเสมอ


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