ฉันต้องการคำอธิบายที่ดี (มีการอ้างอิงเป็นบวก) ในสัญกรณ์ชิ้นของ Python
สำหรับฉันแล้วสัญกรณ์นี้ต้องมีการหยิบขึ้นมาบ้าง
มันดูมีพลังมาก แต่ฉันก็ไม่ได้เอาหัวไปรอบ ๆ
ฉันต้องการคำอธิบายที่ดี (มีการอ้างอิงเป็นบวก) ในสัญกรณ์ชิ้นของ Python
สำหรับฉันแล้วสัญกรณ์นี้ต้องมีการหยิบขึ้นมาบ้าง
มันดูมีพลังมาก แต่ฉันก็ไม่ได้เอาหัวไปรอบ ๆ
คำตอบ:
มันค่อนข้างง่ายจริงๆ:
a[start:stop] # items start through stop-1
a[start:] # items start through the rest of the array
a[:stop] # items from the beginning through stop-1
a[:] # a copy of the whole array
นอกจากนี้ยังมีstep
ค่าซึ่งสามารถใช้กับสิ่งใด ๆ ข้างต้น:
a[start:stop:step] # start through not past stop, by step
จุดสำคัญที่ต้องจำคือ:stop
ค่าหมายถึงค่าแรกที่ไม่ได้อยู่ในส่วนที่เลือก ดังนั้นความแตกต่างระหว่างstop
และstart
คือจำนวนขององค์ประกอบที่เลือก (ถ้าstep
เป็น 1 คือค่าเริ่มต้น)
คุณลักษณะอื่น ๆ คือstart
หรือstop
อาจเป็นจำนวนลบซึ่งหมายความว่านับจากจุดสิ้นสุดของอาร์เรย์แทนการเริ่มต้น ดังนั้น:
a[-1] # last item in the array
a[-2:] # last two items in the array
a[:-2] # everything except the last two items
ในทำนองเดียวกันstep
อาจเป็นจำนวนลบ:
a[::-1] # all items in the array, reversed
a[1::-1] # the first two items, reversed
a[:-3:-1] # the last two items, reversed
a[-3::-1] # everything except the last two items, reversed
Python นั้นใจดีกับโปรแกรมเมอร์หากมีรายการน้อยกว่าที่คุณต้องการ ตัวอย่างเช่นถ้าคุณถามa[:-2]
และa
มีเพียงองค์ประกอบเดียวคุณจะได้รับรายการว่างเปล่าแทนที่จะเกิดข้อผิดพลาด บางครั้งคุณอาจต้องการข้อผิดพลาดดังนั้นคุณต้องระวังว่าสิ่งนี้อาจเกิดขึ้น
slice()
วัตถุตัวดำเนินการแบ่ง[]
กำลังถูกใช้จริงในรหัสข้างต้นกับslice()
วัตถุที่ใช้:
สัญกรณ์ (ซึ่งใช้ได้ภายในเท่านั้น[]
) คือ:
a[start:stop:step]
เทียบเท่ากับ:
a[slice(start, stop, step)]
วัตถุชิ้นยังทำงานแตกต่างกันเล็กน้อยขึ้นอยู่กับจำนวนของอาร์กิวเมนต์เช่นเดียวกับrange()
ทั้งสองslice(stop)
และslice(start, stop[, step])
ได้รับการสนับสนุน หากต้องการข้ามระบุอาร์กิวเมนต์ให้หนึ่งอาจจะใช้None
เพื่อให้เช่นa[start:]
เทียบเท่ากับa[slice(start, None)]
หรือเทียบเท่ากับa[::-1]
a[slice(None, None, -1)]
ในขณะที่:
สัญกรณ์ที่ใช้เป็นประโยชน์อย่างมากสำหรับการแบ่งส่วนอย่างง่ายการใช้slice()
วัตถุอย่างชัดเจนทำให้การสร้างการแบ่งตามโปรแกรมแบบง่าย
None
ช่องว่างใด ๆ ตัวอย่างเช่น[None:None]
ทำสำเนาทั้งหมด สิ่งนี้มีประโยชน์เมื่อคุณต้องการระบุจุดสิ้นสุดของช่วงโดยใช้ตัวแปรและจำเป็นต้องรวมรายการสุดท้าย
del
สัญกรณ์ wrt slice โดยเฉพาะอย่างยิ่งdel arr[:]
ไม่ชัดเจนในทันที ("arr [:] ทำสำเนาจึงลบสำเนานั้น ???" ฯลฯ )
หลามกวดวิชาพูดคุยเกี่ยวกับเรื่องนี้ (เลื่อนลงเล็กน้อยจนกว่าคุณจะได้รับการมีส่วนร่วมเกี่ยวกับการหั่น)
แผนภาพศิลปะ ASCII นั้นมีประโยชน์เช่นกันสำหรับการจดจำว่าชิ้นงานเป็นอย่างไร:
+---+---+---+---+---+---+
| P | y | t | h | o | n |
+---+---+---+---+---+---+
0 1 2 3 4 5 6
-6 -5 -4 -3 -2 -1
วิธีการหนึ่งที่จะจำวิธีการทำงานชิ้นคือการคิดของดัชนีชี้ระหว่างตัวละครกับขอบด้านซ้ายของตัวอักษรตัวแรกเลข 0 แล้วขอบด้านขวาของตัวอักษรตัวสุดท้ายของสตริงของnตัวละครมีดัชนีn
a[-4,-6,-1]
จะเป็นแต่มันเป็นyP
ty
สิ่งที่ใช้งานได้เสมอคือการคิดเป็นตัวละครหรือสล็อตและใช้การจัดทำดัชนีเป็นช่วงเปิดครึ่ง - เปิดขวาถ้าก้าวบวก, เปิดซ้ายถ้าก้าวย่างเชิงลบ
x[:0]
เมื่อเริ่มต้นจากจุดเริ่มต้น) ดังนั้นคุณจะต้องใช้อาร์เรย์ตัวพิมพ์เล็กพิเศษ : /
การแจกแจงความเป็นไปได้ที่ไวยากรณ์อนุญาตให้ทำได้:
>>> seq[:] # [seq[0], seq[1], ..., seq[-1] ]
>>> seq[low:] # [seq[low], seq[low+1], ..., seq[-1] ]
>>> seq[:high] # [seq[0], seq[1], ..., seq[high-1]]
>>> seq[low:high] # [seq[low], seq[low+1], ..., seq[high-1]]
>>> seq[::stride] # [seq[0], seq[stride], ..., seq[-1] ]
>>> seq[low::stride] # [seq[low], seq[low+stride], ..., seq[-1] ]
>>> seq[:high:stride] # [seq[0], seq[stride], ..., seq[high-1]]
>>> seq[low:high:stride] # [seq[low], seq[low+stride], ..., seq[high-1]]
แน่นอนถ้า(high-low)%stride != 0
จากนั้นจุดสิ้นสุดจะต่ำกว่าhigh-1
เล็กน้อย
หากstride
เป็นค่าลบการสั่งซื้อจะเปลี่ยนไปเล็กน้อยเนื่องจากเรานับถอยหลัง:
>>> seq[::-stride] # [seq[-1], seq[-1-stride], ..., seq[0] ]
>>> seq[high::-stride] # [seq[high], seq[high-stride], ..., seq[0] ]
>>> seq[:low:-stride] # [seq[-1], seq[-1-stride], ..., seq[low+1]]
>>> seq[high:low:-stride] # [seq[high], seq[high-stride], ..., seq[low+1]]
การแบ่งส่วนข้อมูลแบบขยาย (ด้วยเครื่องหมายจุลภาคและจุดไข่ปลา) ส่วนใหญ่จะใช้โดยโครงสร้างข้อมูลพิเศษเท่านั้น (เช่น NumPy) ลำดับขั้นพื้นฐานไม่สนับสนุนพวกเขา
>>> class slicee:
... def __getitem__(self, item):
... return repr(item)
...
>>> slicee()[0, 1:2, ::5, ...]
'(0, slice(1, 2, None), slice(None, None, 5), Ellipsis)'
repr
__getitem__
คือ; apple[slice(4, -4, -1)]
ตัวอย่างของคุณจะเทียบเท่ากับ
คำตอบข้างต้นไม่ได้พูดถึงการแบ่งชิ้น เพื่อให้เข้าใจถึงการกำหนดชิ้นเป็นประโยชน์ในการเพิ่มแนวคิดอื่นให้กับศิลปะ ASCII:
+---+---+---+---+---+---+
| P | y | t | h | o | n |
+---+---+---+---+---+---+
Slice position: 0 1 2 3 4 5 6
Index position: 0 1 2 3 4 5
>>> p = ['P','y','t','h','o','n']
# Why the two sets of numbers:
# indexing gives items, not lists
>>> p[0]
'P'
>>> p[5]
'n'
# Slicing gives lists
>>> p[0:1]
['P']
>>> p[0:2]
['P','y']
หนึ่งฮิวริสติกคือหนึ่งส่วนจากศูนย์ถึง n คิดว่า: "ศูนย์คือจุดเริ่มต้นเริ่มต้นที่จุดเริ่มต้นและนำรายการ n ในรายการ"
>>> p[5] # the last of six items, indexed from zero
'n'
>>> p[0:5] # does NOT include the last item!
['P','y','t','h','o']
>>> p[0:6] # not p[0:5]!!!
['P','y','t','h','o','n']
ฮิวริสติกอื่นคือ "สำหรับชิ้นส่วนใด ๆ เปลี่ยนจุดเริ่มต้นเป็นศูนย์ใช้ฮิวริสติกก่อนหน้าเพื่อสิ้นสุดรายการจากนั้นนับจำนวนแรกกลับไปที่รายการสับจากจุดเริ่มต้น"
>>> p[0:4] # Start at the beginning and count out 4 items
['P','y','t','h']
>>> p[1:4] # Take one item off the front
['y','t','h']
>>> p[2:4] # Take two items off the front
['t','h']
# etc.
กฎข้อแรกของการกำหนดค่าชิ้นคือเนื่องจากการแบ่งการส่งคืนรายการการมอบหมายชิ้นต้องใช้รายการ (หรืออื่น ๆ iterable):
>>> p[2:3]
['t']
>>> p[2:3] = ['T']
>>> p
['P','y','T','h','o','n']
>>> p[2:3] = 't'
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: can only assign an iterable
กฎข้อที่สองของการกำหนดชิ้นซึ่งคุณสามารถเห็นด้านบนคือส่วนใดของรายการที่ถูกส่งคืนโดยการจัดทำดัชนีชิ้นนั่นคือส่วนเดียวกันที่เปลี่ยนแปลงโดยการกำหนดชิ้น:
>>> p[2:4]
['T','h']
>>> p[2:4] = ['t','r']
>>> p
['P','y','t','r','o','n']
กฎข้อที่สามของการกำหนดชิ้นคือรายการที่กำหนด (iterable) ไม่จำเป็นต้องมีความยาวเท่ากัน ชิ้นส่วนที่จัดทำดัชนีนั้นถูกตัดออกและแทนที่สิ่งที่กำหนด:
>>> p = ['P','y','t','h','o','n'] # Start over
>>> p[2:4] = ['s','p','a','m']
>>> p
['P','y','s','p','a','m','o','n']
ส่วนที่ยากที่สุดที่จะคุ้นเคยคือการมอบหมายให้กับชิ้นส่วนที่ว่างเปล่า การใช้ฮิวริสติกที่ 1 และ 2 ช่วยให้คุณสามารถจัดทำดัชนีชิ้นส่วนที่ว่างได้ง่าย:
>>> p = ['P','y','t','h','o','n']
>>> p[0:4]
['P','y','t','h']
>>> p[1:4]
['y','t','h']
>>> p[2:4]
['t','h']
>>> p[3:4]
['h']
>>> p[4:4]
[]
และจากนั้นเมื่อคุณเห็นว่าการแบ่งส่วนเป็นชิ้นว่างเปล่าก็สมเหตุสมผลเช่นกัน:
>>> p = ['P','y','t','h','o','n']
>>> p[2:4] = ['x','y'] # Assigned list is same length as slice
>>> p
['P','y','x','y','o','n'] # Result is same length
>>> p = ['P','y','t','h','o','n']
>>> p[3:4] = ['x','y'] # Assigned list is longer than slice
>>> p
['P','y','t','x','y','o','n'] # The result is longer
>>> p = ['P','y','t','h','o','n']
>>> p[4:4] = ['x','y']
>>> p
['P','y','t','h','x','y','o','n'] # The result is longer still
โปรดทราบว่าเนื่องจากเราไม่ได้เปลี่ยนจำนวนชิ้นที่สอง (4) รายการที่แทรกไว้จะเรียงซ้อนกันเสมอกับ 'o' แม้ว่าเราจะกำหนดให้ชิ้นว่างเปล่าก็ตาม ดังนั้นตำแหน่งสำหรับการกำหนดชิ้นว่างจึงเป็นส่วนขยายตรรกะของตำแหน่งสำหรับชิ้นส่วนที่ไม่ว่างเปล่า
การสำรองข้อมูลเล็กน้อยจะเกิดอะไรขึ้นเมื่อคุณเดินไปเรื่อย ๆ กับขบวนนับนับชิ้นเริ่มต้นของเรา
>>> p = ['P','y','t','h','o','n']
>>> p[0:4]
['P','y','t','h']
>>> p[1:4]
['y','t','h']
>>> p[2:4]
['t','h']
>>> p[3:4]
['h']
>>> p[4:4]
[]
>>> p[5:4]
[]
>>> p[6:4]
[]
เมื่อหั่นเสร็จแล้วคุณก็เรียบร้อย มันไม่ได้เริ่มแบ่งไปข้างหลัง ใน Python คุณจะไม่ได้รับความก้าวหน้าเชิงลบเว้นแต่คุณจะขออย่างชัดเจนโดยใช้หมายเลขติดลบ
>>> p[5:3:-1]
['n','o']
มีผลบางอย่างแปลก ๆ กับกฎ "เมื่อคุณทำเสร็จแล้ว"
>>> p[4:4]
[]
>>> p[5:4]
[]
>>> p[6:4]
[]
>>> p[6]
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
IndexError: list index out of range
ในความเป็นจริงเมื่อเทียบกับการจัดทำดัชนีการแบ่ง Python เป็นข้อผิดพลาดที่ผิดปกติ:
>>> p[100:200]
[]
>>> p[int(2e99):int(1e99)]
[]
บางครั้งสิ่งนี้อาจมีประโยชน์ แต่ก็อาจนำไปสู่พฤติกรรมที่ค่อนข้างแปลก:
>>> p
['P', 'y', 't', 'h', 'o', 'n']
>>> p[int(2e99):int(1e99)] = ['p','o','w','e','r']
>>> p
['P', 'y', 't', 'h', 'o', 'n', 'p', 'o', 'w', 'e', 'r']
ขึ้นอยู่กับใบสมัครของคุณนั่นอาจ ... หรืออาจจะไม่ใช่ ... เป็นสิ่งที่คุณหวังไว้ที่นั่น!
ด้านล่างนี้เป็นข้อความของคำตอบดั้งเดิมของฉัน มันมีประโยชน์กับคนจำนวนมากดังนั้นฉันไม่ต้องการลบ
>>> r=[1,2,3,4]
>>> r[1:1]
[]
>>> r[1:1]=[9,8]
>>> r
[1, 9, 8, 2, 3, 4]
>>> r[1:1]=['blah']
>>> r
[1, 'blah', 9, 8, 2, 3, 4]
สิ่งนี้อาจอธิบายความแตกต่างระหว่างการแบ่งและการจัดทำดัชนี
อธิบายสัญกรณ์ของ Python
ในระยะสั้นทวิภาค ( :
) ในสัญกรณ์ห้อย ( subscriptable[subscriptarg]
) ให้สัญกรณ์ชิ้น - ซึ่งมีข้อโต้แย้งทางเลือกstart
, stop
, step
:
sliceable[start:stop:step]
Python slicing เป็นวิธีที่รวดเร็วในการคำนวณเพื่อเข้าถึงส่วนต่างๆของข้อมูลของคุณ ในความคิดของฉันการเป็นโปรแกรมเมอร์ Python ระดับกลางเป็นหนึ่งในแง่มุมของภาษาที่จำเป็นต้องคุ้นเคย
ในการเริ่มต้นให้นิยามคำศัพท์สองสามคำ:
start:ดัชนีเริ่มต้นของชิ้นมันจะรวมองค์ประกอบที่ดัชนีนี้เว้นแต่ว่าจะเป็นเช่นเดียวกับหยุดเริ่มต้นที่ 0 คือดัชนีแรก ถ้ามันเป็นลบมันหมายถึงการเริ่มต้น
n
รายการจากจุดสิ้นสุดหยุด:ดัชนีสิ้นสุดของชิ้นมันไม่รวมองค์ประกอบที่ดัชนีนี้เริ่มต้นที่ความยาวของลำดับที่ถูกหั่นนั่นคือถึงและรวมถึงจุดสิ้นสุด
ขั้นตอน:จำนวนที่ดัชนีเพิ่มขึ้นค่าเริ่มต้นที่ 1 หากเป็นค่าลบคุณจะแบ่งส่วนที่ทำซ้ำได้ในสิ่งที่ตรงกันข้าม
คุณสามารถสร้างตัวเลขที่เป็นบวกหรือลบได้ ความหมายของตัวเลขบวกนั้นตรงไปตรงมา แต่สำหรับตัวเลขลบเช่นเดียวกับดัชนีใน Python คุณจะนับถอยหลังตั้งแต่ต้นจนจบสำหรับจุดเริ่มต้นและหยุดและสำหรับขั้นตอนคุณเพียงแค่ลดดัชนีของคุณลง ตัวอย่างนี้มาจากบทช่วยสอนของเอกสารแต่ฉันได้แก้ไขเล็กน้อยเพื่อระบุว่ารายการใดในลำดับที่อ้างอิงดัชนีแต่ละรายการ:
+---+---+---+---+---+---+
| P | y | t | h | o | n |
+---+---+---+---+---+---+
0 1 2 3 4 5
-6 -5 -4 -3 -2 -1
ในการใช้เครื่องหมายแบ่งที่มีลำดับที่สนับสนุนคุณต้องรวมอย่างน้อยหนึ่งโคลอนในวงเล็บเหลี่ยมที่ตามลำดับ (ซึ่งใช้__getitem__
วิธีการของลำดับตามจริงตามแบบจำลองข้อมูล Python )
สัญกรณ์ Slice ทำงานเช่นนี้:
sequence[start:stop:step]
และจำได้ว่ามีค่าเริ่มต้นสำหรับการเริ่มต้น , หยุดและขั้นตอนเพื่อที่จะเข้าถึงเริ่มต้นเพียงแค่ปล่อยออกมาโต้แย้ง
สัญกรณ์ Slice เพื่อรับองค์ประกอบเก้าชิ้นสุดท้ายจากรายการ (หรือลำดับอื่น ๆ ที่สนับสนุนมันเช่นสตริง) จะมีลักษณะดังนี้:
my_list[-9:]
เมื่อฉันเห็นสิ่งนี้ฉันอ่านส่วนในวงเล็บเป็น "9 ตั้งแต่ต้นจนจบ" (ที่จริงแล้วฉันย่อว่าจิตใจเป็น "-9, on")
สัญกรณ์เต็มคือ
my_list[-9:None:None]
และเพื่อแทนที่ค่าเริ่มต้น (ที่จริงแล้วเมื่อstep
เป็นค่าลบstop
ค่าเริ่มต้นคือ-len(my_list) - 1
ดังนั้นNone
สำหรับการหยุดจริง ๆ ก็หมายความว่ามันจะไปยังขั้นตอนสุดท้ายที่จะนำไปใช้)
my_list[-9:len(my_list):1]
ลำไส้ใหญ่ , :
เป็นสิ่งที่บอกว่างูหลามคุณให้มันเป็นชิ้นและไม่ได้เป็นดัชนีปกติ นั่นเป็นเหตุผลว่าทำไมการทำสำเนารายการตื้น ๆ ใน Python 2 จึงเป็นวิธีที่แปลกประหลาด
list_copy = sequence[:]
และล้างพวกเขาด้วย:
del my_list[:]
(Python 3 ได้รับ a list.copy
และlist.clear
method)
step
ใดที่เป็นค่าลบค่าเริ่มต้นstart
และstop
เปลี่ยนแปลงโดยค่าเริ่มต้นเมื่อstep
อาร์กิวเมนต์เป็นที่ว่างเปล่า (หรือNone
) +1
มันถูกกำหนดให้
แต่คุณสามารถผ่านเป็นจำนวนเต็มลบได้และรายการ (หรือส่วนแบ่งมาตรฐานอื่น ๆ ส่วนใหญ่) จะถูกแบ่งเป็นส่วน ๆ จากจุดเริ่มต้นไปยังจุดเริ่มต้น
ดังนั้นชิ้นเชิงลบจะเปลี่ยนค่าเริ่มต้นstart
และstop
!
ฉันต้องการสนับสนุนให้ผู้ใช้อ่านแหล่งรวมทั้งเอกสารประกอบ ซอร์สโค้ดของชิ้นวัตถุและตรรกะนี้จะพบได้ที่นี่ ก่อนอื่นเราพิจารณาว่าstep
เป็นลบหรือไม่:
step_is_negative = step_sign < 0;
ถ้าเป็นเช่นนั้นขอบล่าง-1
หมายถึงเราฝานไปจนถึงและรวมถึงจุดเริ่มต้นและขอบเขตบนคือความยาวลบ 1 ซึ่งหมายถึงเราเริ่มต้นที่จุดสิ้นสุด (หมายเหตุว่าความหมายของนี้-1
เป็นที่แตกต่างจาก-1
ที่ผู้ใช้อาจจะผ่านการจัดทำดัชนีในหลามแสดงให้เห็นรายการสุดท้าย.)
if (step_is_negative) { lower = PyLong_FromLong(-1L); if (lower == NULL) goto error; upper = PyNumber_Add(length, lower); if (upper == NULL) goto error; }
มิฉะนั้นstep
เป็นบวกและขอบเขตล่างจะเป็นศูนย์และขอบบน (ซึ่งเราไปถึง แต่ไม่รวม) ความยาวของรายการที่หั่นบาง ๆ
else { lower = _PyLong_Zero; Py_INCREF(lower); upper = length; Py_INCREF(upper); }
จากนั้นเราอาจต้องใช้ค่าเริ่มต้นสำหรับstart
และstop
- ค่าเริ่มต้นสำหรับนั้นstart
จะถูกคำนวณเป็นขอบเขตบนเมื่อstep
เป็นลบ:
if (self->start == Py_None) { start = step_is_negative ? upper : lower; Py_INCREF(start); }
และstop
ขอบเขตล่าง:
if (self->stop == Py_None) { stop = step_is_negative ? lower : upper; Py_INCREF(stop); }
คุณอาจพบว่ามีประโยชน์ในการแยกการขึ้นรูปชิ้นส่วนจากการส่งผ่านไปยังlist.__getitem__
วิธีการ ( นั่นคือสิ่งที่วงเล็บเหลี่ยมทำ ) แม้ว่าคุณจะไม่ใหม่ แต่ก็ทำให้โค้ดของคุณอ่านง่ายขึ้นเพื่อให้ผู้อื่นที่อาจต้องอ่านรหัสของคุณสามารถเข้าใจสิ่งที่คุณกำลังทำอยู่ได้ง่ายขึ้น
อย่างไรก็ตามคุณไม่สามารถกำหนดจำนวนเต็มที่คั่นด้วยโคลอนให้กับตัวแปรได้ คุณต้องใช้วัตถุชิ้น:
last_nine_slice = slice(-9, None)
อาร์กิวเมนต์ที่สองNone
เป็นสิ่งจำเป็นเพื่อให้อาร์กิวเมนต์แรกจะถูกแปลเป็นstart
อาร์กิวเมนต์มิฉะนั้นก็จะเป็นstop
ข้อโต้แย้ง
จากนั้นคุณสามารถส่งวัตถุชิ้นไปยังลำดับของคุณ:
>>> list(range(100))[last_nine_slice]
[91, 92, 93, 94, 95, 96, 97, 98, 99]
เป็นเรื่องที่น่าสนใจที่ช่วงนั้นจะแบ่งเป็นส่วน ๆ :
>>> range(100)[last_nine_slice]
range(91, 100)
itertools.islice
ตั้งแต่ชิ้นของรายการหลามสร้างวัตถุใหม่ในความทรงจำอีกฟังก์ชั่นสำคัญที่จะต้องระวังก็คือ โดยทั่วไปแล้วคุณจะต้องวนซ้ำไปเรื่อย ๆ ไม่ใช่แค่สร้างหน่วยความจำแบบสแตติก islice
เหมาะสำหรับสิ่งนี้ ข้อแม้ก็ไม่ได้สนับสนุนข้อโต้แย้งในทางลบต่อstart
, stop
หรือstep
ดังนั้นหากที่เป็นปัญหาคุณอาจจำเป็นต้องคำนวณดัชนีหรือย้อนกลับ iterable ล่วงหน้า
length = 100
last_nine_iter = itertools.islice(list(range(length)), length-9, None, 1)
list_last_nine = list(last_nine_iter)
และตอนนี้:
>>> list_last_nine
[91, 92, 93, 94, 95, 96, 97, 98, 99]
ข้อเท็จจริงที่ว่าตัวแบ่งส่วนรายการทำสำเนาเป็นคุณลักษณะของรายการเอง หากคุณกำลังแบ่งวัตถุขั้นสูงเช่น Pandas DataFrame มันอาจส่งคืนมุมมองบนต้นฉบับไม่ใช่สำเนา
และบางสิ่งที่ฉันไม่เห็นได้ชัดเมื่อฉันเห็นไวยากรณ์การแบ่งเป็นครั้งแรก:
>>> x = [1,2,3,4,5,6]
>>> x[::-1]
[6,5,4,3,2,1]
วิธีง่ายๆในการย้อนกลับลำดับ!
และถ้าคุณต้องการด้วยเหตุผลบางอย่างทุกรายการที่สองในลำดับที่กลับรายการ:
>>> x = [1,2,3,4,5,6]
>>> x[::-2]
[6,4,2]
ใน Python 2.7
การแบ่งส่วนใน Python
[a:b:c]
len = length of string, tuple or list
c -- default is +1. The sign of c indicates forward or backward, absolute value of c indicates steps. Default is forward with step size 1. Positive means forward, negative means backward.
a -- When c is positive or blank, default is 0. When c is negative, default is -1.
b -- When c is positive or blank, default is len. When c is negative, default is -(len+1).
การทำความเข้าใจกับการกำหนดดัชนีมีความสำคัญมาก
In forward direction, starts at 0 and ends at len-1
In backward direction, starts at -1 and ends at -len
เมื่อคุณพูดว่า [a: b: c] คุณกำลังพูดโดยขึ้นอยู่กับเครื่องหมายของ c (ไปข้างหน้าหรือข้างหลัง) เริ่มต้นที่ a และสิ้นสุดที่ b (ยกเว้นองค์ประกอบที่ดัชนี bth) ใช้กฎการจัดทำดัชนีด้านบนและจำไว้ว่าคุณจะพบองค์ประกอบในช่วงนี้เท่านั้น:
-len, -len+1, -len+2, ..., 0, 1, 2,3,4 , len -1
แต่ช่วงนี้ยังคงดำเนินต่อไปในทั้งสองทิศทาง:
...,-len -2 ,-len-1,-len, -len+1, -len+2, ..., 0, 1, 2,3,4 , len -1, len, len +1, len+2 , ....
ตัวอย่างเช่น:
0 1 2 3 4 5 6 7 8 9 10 11
a s t r i n g
-9 -8 -7 -6 -5 -4 -3 -2 -1
หากคุณเลือก a, b และ c อนุญาตให้เหลื่อมกับช่วงข้างบนในขณะที่คุณใช้กฎสำหรับ a, b, c ข้างต้นคุณจะได้รับรายการที่มีองค์ประกอบ (สัมผัสระหว่างการสำรวจเส้นทาง) หรือคุณจะได้รายการที่ว่างเปล่า
สิ่งหนึ่งที่สุดท้าย: ถ้า a และ b เท่ากันคุณก็จะได้รายการว่าง:
>>> l1
[2, 3, 4]
>>> l1[:]
[2, 3, 4]
>>> l1[::-1] # a default is -1 , b default is -(len+1)
[4, 3, 2]
>>> l1[:-4:-1] # a default is -1
[4, 3, 2]
>>> l1[:-3:-1] # a default is -1
[4, 3]
>>> l1[::] # c default is +1, so a default is 0, b default is len
[2, 3, 4]
>>> l1[::-1] # c is -1 , so a default is -1 and b default is -(len+1)
[4, 3, 2]
>>> l1[-100:-200:-1] # Interesting
[]
>>> l1[-1:-200:-1] # Interesting
[4, 3, 2]
>>> l1[-1:-1:1]
[]
>>> l1[-1:5:1] # Interesting
[4]
>>> l1[1:-7:1]
[]
>>> l1[1:-7:-1] # Interesting
[3, 2]
>>> l1[:-2:-2] # a default is -1, stop(b) at -2 , step(c) by 2 in reverse direction
[4]
a = [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 ]; a[:-2:-2]
ซึ่งส่งผลให้[9]
พบกับตารางที่ยอดเยี่ยมนี้ได้ที่http://wiki.python.org/moin/MovingToPythonFromOtherLanguages
Python indexes and slices for a six-element list.
Indexes enumerate the elements, slices enumerate the spaces between the elements.
Index from rear: -6 -5 -4 -3 -2 -1 a=[0,1,2,3,4,5] a[1:]==[1,2,3,4,5]
Index from front: 0 1 2 3 4 5 len(a)==6 a[:5]==[0,1,2,3,4]
+---+---+---+---+---+---+ a[0]==0 a[:-2]==[0,1,2,3]
| a | b | c | d | e | f | a[5]==5 a[1:2]==[1]
+---+---+---+---+---+---+ a[-1]==5 a[1:-1]==[1,2,3,4]
Slice from front: : 1 2 3 4 5 : a[-2]==4
Slice from rear: : -5 -4 -3 -2 -1 :
b=a[:]
b==[0,1,2,3,4,5] (shallow copy of a)
หลังจากใช้ไปสักพักฉันก็รู้ว่าคำอธิบายที่ง่ายที่สุดคือมันเหมือนกับสิ่งที่ขัดแย้งกันในfor
วง ...
(from:to:step)
ใด ๆ ของพวกเขาเป็นตัวเลือก:
(:to:step)
(from::step)
(from:to)
จากนั้นการจัดทำดัชนีเชิงลบเพียงต้องการให้คุณเพิ่มความยาวของสตริงลงในดัชนีลบเพื่อทำความเข้าใจ
ใช้ได้กับฉันแล้ว ...
ฉันพบว่ามันง่ายกว่าที่จะจำว่ามันทำงานอย่างไรและจากนั้นฉันสามารถหาชุดค่าผสมแบบเริ่ม / หยุด / ขั้นตอนที่เฉพาะเจาะจงได้
เป็นคำแนะนำให้เข้าใจrange()
ก่อน:
def range(start=0, stop, step=1): # Illegal syntax, but that's the effect
i = start
while (i < stop if step > 0 else i > stop):
yield i
i += step
เริ่มต้นจากstart
, เพิ่มขึ้นโดยไม่ถึงstep
stop
ง่ายมาก.
สิ่งที่ต้องจดจำเกี่ยวกับขั้นตอนเชิงลบคือstop
จุดสิ้นสุดที่ถูกแยกออกเสมอไม่ว่าจะสูงหรือต่ำกว่า หากคุณต้องการให้ชิ้นงานเรียงกันเรียงกันมันจะสะอาดกว่าถ้าทำการกลับรายการแยกกัน: เช่น'abcde'[1:-2][::-1]
ตัดเศษถ่านหนึ่งอันออกจากซ้ายสองจากขวาจากนั้นกลับด้าน (ดูเพิ่มเติมที่reversed()
)
การแบ่งส่วนลำดับเหมือนกันยกเว้นอันดับแรกจะทำให้ดัชนีเชิงลบเป็นปกติและจะไม่สามารถออกไปนอกลำดับได้:
สิ่งที่ต้องทำ : รหัสด้านล่างมีข้อผิดพลาดกับ "ไม่เคยออกไปข้างนอกลำดับ" เมื่อ abs (ขั้นตอน)> 1; ฉันคิดว่าฉันแก้ไขมันให้ถูกต้อง แต่มันยากที่จะเข้าใจ
def this_is_how_slicing_works(seq, start=None, stop=None, step=1):
if start is None:
start = (0 if step > 0 else len(seq)-1)
elif start < 0:
start += len(seq)
if not 0 <= start < len(seq): # clip if still outside bounds
start = (0 if step > 0 else len(seq)-1)
if stop is None:
stop = (len(seq) if step > 0 else -1) # really -1, not last element
elif stop < 0:
stop += len(seq)
for i in range(start, stop, step):
if 0 <= i < len(seq):
yield seq[i]
ไม่ต้องกังวลเกี่ยวกับis None
รายละเอียด - เพียงจำไว้ว่าการละเว้นstart
และ / หรือstop
ทำสิ่งที่ถูกต้องเสมอเพื่อให้ลำดับทั้งหมด
ดัชนีเชิงลบ Normalizing แรกที่ช่วยให้การเริ่มต้นและ / หรือหยุดที่จะนับจากปลายอิสระ: แม้จะมี'abcde'[1:-2] == 'abcde'[1:3] == 'bc'
range(1,-2) == []
การปรับสภาพบางครั้งคิดว่าเป็น "โมดูโลความยาว" แต่โปรดทราบว่ามันเพิ่มความยาวเพียงครั้งเดียว: เช่น'abcde'[-53:42]
เป็นเพียงสายอักขระทั้งหมด
this_is_how_slicing_works
นี้ไม่เหมือนกับ python slice EG [0, 1, 2][-5:3:3]
จะได้ [0] เป็นไพ ธ อน แต่list(this_is_how_slicing_works([0, 1, 2], -5, 3, 3))
รับ [1]
range(4)[-200:200:3] == [0, 3]
list(this_is_how_slicing_works([0, 1, 2, 3], -200, 200, 3)) == [2]
ฉันif 0 <= i < len(seq):
เป็นความพยายามในการใช้งาน "ไม่เคยออกนอกลำดับ" เพียง แต่ผิดสำหรับขั้นตอน> 1 ฉันจะเขียนมันใหม่ในวันนี้ (พร้อมการทดสอบ)
ฉันใช้วิธีการ "ชี้ดัชนีระหว่างองค์ประกอบ" ในการคิดเกี่ยวกับมันด้วยตัวเอง แต่วิธีหนึ่งในการอธิบายซึ่งบางครั้งช่วยให้ผู้อื่นได้รับสิ่งนี้:
mylist[X:Y]
X คือดัชนีขององค์ประกอบแรกที่คุณต้องการ
Y คือดัชนีองค์ประกอบแรกที่คุณไม่ต้องการ
Index:
------------>
0 1 2 3 4
+---+---+---+---+---+
| a | b | c | d | e |
+---+---+---+---+---+
0 -4 -3 -2 -1
<------------
Slice:
<---------------|
|--------------->
: 1 2 3 4 :
+---+---+---+---+---+
| a | b | c | d | e |
+---+---+---+---+---+
: -4 -3 -2 -1 :
|--------------->
<---------------|
ฉันหวังว่านี่จะช่วยให้คุณสร้างแบบจำลองรายการใน Python
การอ้างอิง: http://wiki.python.org/moin/MovingToPythonFromOtherLanguages
สัญกรณ์การแบ่งหลาม:
a[start:end:step]
start
และend
ค่าลบถูกตีความว่าสัมพันธ์กับจุดสิ้นสุดของลำดับend
ระบุตำแหน่งหลังจากองค์ประกอบสุดท้ายที่จะรวม[+0:-0:1]
ค่าว่างเปล่าจะผิดนัดดังต่อไปนี้:start
และend
สัญกรณ์ขยายไปถึงเมทริกซ์ (numpy) และอาร์เรย์หลายมิติ ตัวอย่างเช่นหากต้องการแบ่งคอลัมน์ทั้งหมดคุณสามารถใช้:
m[::,0:2:] ## slice the first two columns
ชิ้นถือการอ้างอิงไม่คัดลอกขององค์ประกอบอาร์เรย์ deepcopy()
หากคุณต้องการที่จะทำสำเนาแยกต่างหากอาร์เรย์คุณสามารถใช้
คุณยังสามารถใช้การกำหนดชิ้นเพื่อลบองค์ประกอบหนึ่งรายการหรือมากกว่าจากรายการ:
r = [1, 'blah', 9, 8, 2, 3, 4]
>>> r[1:4] = []
>>> r
[1, 2, 3, 4]
นี่เป็นเพียงข้อมูลเพิ่มเติม ... พิจารณารายการด้านล่าง
>>> l=[12,23,345,456,67,7,945,467]
ไม่กี่เทคนิคอื่น ๆ สำหรับการย้อนกลับรายการ:
>>> l[len(l):-len(l)-1:-1]
[467, 945, 7, 67, 456, 345, 23, 12]
>>> l[:-len(l)-1:-1]
[467, 945, 7, 67, 456, 345, 23, 12]
>>> l[len(l)::-1]
[467, 945, 7, 67, 456, 345, 23, 12]
>>> l[::-1]
[467, 945, 7, 67, 456, 345, 23, 12]
>>> l[-1:-len(l)-1:-1]
[467, 945, 7, 67, 456, 345, 23, 12]
นี่คือวิธีที่ฉันสอนการแบ่งส่วนสำหรับมือใหม่:
ทำความเข้าใจความแตกต่างระหว่างการจัดทำดัชนีและการแบ่งส่วน:
Wiki Python มีภาพที่น่าทึ่งซึ่งแยกการจัดทำดัชนีและการแบ่ง
มันเป็นรายการที่มีหกองค์ประกอบในนั้น เพื่อให้เข้าใจการแบ่งส่วนได้ดีขึ้นให้พิจารณารายการนั้นเป็นชุดของหกกล่องที่วางไว้ด้วยกัน แต่ละกล่องมีตัวอักษรอยู่ในนั้น
การจัดทำดัชนีเป็นเหมือนการจัดการกับเนื้อหาของกล่อง คุณสามารถตรวจสอบเนื้อหาของกล่องใด ๆ แต่คุณไม่สามารถตรวจสอบเนื้อหาของกล่องหลายกล่องพร้อมกัน คุณสามารถแทนที่เนื้อหาของกล่อง แต่คุณไม่สามารถวางสองลูกในกล่องเดียวหรือแทนที่สองลูกในเวลาเดียวกัน
In [122]: alpha = ['a', 'b', 'c', 'd', 'e', 'f']
In [123]: alpha
Out[123]: ['a', 'b', 'c', 'd', 'e', 'f']
In [124]: alpha[0]
Out[124]: 'a'
In [127]: alpha[0] = 'A'
In [128]: alpha
Out[128]: ['A', 'b', 'c', 'd', 'e', 'f']
In [129]: alpha[0,1]
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
<ipython-input-129-c7eb16585371> in <module>()
----> 1 alpha[0,1]
TypeError: list indices must be integers, not tuple
การแบ่งเป็นเหมือนการจัดการกับกล่องด้วยตัวเอง คุณสามารถหยิบกล่องแรกและวางบนโต๊ะอื่น ในการรับกล่องสิ่งที่คุณต้องรู้ก็คือตำแหน่งของจุดเริ่มต้นและจุดสิ้นสุดของกล่อง
คุณสามารถเลือกสามกล่องแรกหรือสองกล่องสุดท้ายหรือกล่องทั้งหมดระหว่าง 1 ถึง 4 ดังนั้นคุณสามารถเลือกชุดของกล่องใดก็ได้หากคุณทราบจุดเริ่มต้นและจุดสิ้นสุด ตำแหน่งเหล่านี้เรียกว่าตำแหน่งเริ่มและหยุด
สิ่งที่น่าสนใจคือคุณสามารถแทนที่กล่องหลายกล่องพร้อมกัน นอกจากนี้คุณสามารถวางหลายกล่องได้ทุกที่ที่คุณต้องการ
In [130]: alpha[0:1]
Out[130]: ['A']
In [131]: alpha[0:1] = 'a'
In [132]: alpha
Out[132]: ['a', 'b', 'c', 'd', 'e', 'f']
In [133]: alpha[0:2] = ['A', 'B']
In [134]: alpha
Out[134]: ['A', 'B', 'c', 'd', 'e', 'f']
In [135]: alpha[2:2] = ['x', 'xx']
In [136]: alpha
Out[136]: ['A', 'B', 'x', 'xx', 'c', 'd', 'e', 'f']
ขั้นตอน:
จนถึงตอนนี้คุณได้เลือกกล่องอย่างต่อเนื่อง แต่บางครั้งคุณจำเป็นต้องรับอย่างไม่น่าเชื่อ ตัวอย่างเช่นคุณสามารถรับกล่องทุกวินาที คุณสามารถรับกล่องทุก ๆ สามจากตอนท้าย ค่านี้เรียกว่าขนาดขั้นตอน นี่แสดงถึงช่องว่างระหว่างการเลือกรถปิคอัพที่ต่อเนื่องของคุณ ขนาดขั้นตอนควรเป็นค่าบวกหากคุณกำลังเลือกกล่องตั้งแต่ต้นจนจบและในทางกลับกัน
In [137]: alpha = ['a', 'b', 'c', 'd', 'e', 'f']
In [142]: alpha[1:5:2]
Out[142]: ['b', 'd']
In [143]: alpha[-1:-5:-2]
Out[143]: ['f', 'd']
In [144]: alpha[1:5:-2]
Out[144]: []
In [145]: alpha[-1:-5:2]
Out[145]: []
Python แสดงให้เห็นว่าพารามิเตอร์ที่ขาดหายไปได้อย่างไร:
เมื่อแบ่งส่วนถ้าคุณไม่ใช้พารามิเตอร์ใด ๆ Python จะพยายามหาค่าโดยอัตโนมัติ
หากคุณตรวจสอบซอร์สโค้ดของCPythonคุณจะพบฟังก์ชันที่เรียกว่า PySlice_GetIndicesEx () ซึ่งเป็นตัวบ่งชี้ดัชนีเป็นชิ้นสำหรับพารามิเตอร์ที่กำหนด นี่คือรหัสเทียบเท่าแบบลอจิคัลใน Python
ฟังก์ชันนี้ใช้วัตถุ Python และพารามิเตอร์ทางเลือกสำหรับการแบ่งและส่งคืนค่าเริ่มต้นหยุดขั้นตอนและความยาวส่วนสำหรับชิ้นที่ร้องขอ
def py_slice_get_indices_ex(obj, start=None, stop=None, step=None):
length = len(obj)
if step is None:
step = 1
if step == 0:
raise Exception("Step cannot be zero.")
if start is None:
start = 0 if step > 0 else length - 1
else:
if start < 0:
start += length
if start < 0:
start = 0 if step > 0 else -1
if start >= length:
start = length if step > 0 else length - 1
if stop is None:
stop = length if step > 0 else -1
else:
if stop < 0:
stop += length
if stop < 0:
stop = 0 if step > 0 else -1
if stop >= length:
stop = length if step > 0 else length - 1
if (step < 0 and stop >= start) or (step > 0 and start >= stop):
slice_length = 0
elif step < 0:
slice_length = (stop - start + 1)/(step) + 1
else:
slice_length = (stop - start - 1)/(step) + 1
return (start, stop, step, slice_length)
นี่คือความเฉลียวฉลาดที่อยู่ด้านหลังชิ้น เนื่องจาก Python มีฟังก์ชันในตัวที่เรียกว่า slice คุณสามารถผ่านพารามิเตอร์บางตัวและตรวจสอบวิธีการคำนวณพารามิเตอร์ที่ขาดหายไปอย่างชาญฉลาด
In [21]: alpha = ['a', 'b', 'c', 'd', 'e', 'f']
In [22]: s = slice(None, None, None)
In [23]: s
Out[23]: slice(None, None, None)
In [24]: s.indices(len(alpha))
Out[24]: (0, 6, 1)
In [25]: range(*s.indices(len(alpha)))
Out[25]: [0, 1, 2, 3, 4, 5]
In [26]: s = slice(None, None, -1)
In [27]: range(*s.indices(len(alpha)))
Out[27]: [5, 4, 3, 2, 1, 0]
In [28]: s = slice(None, 3, -1)
In [29]: range(*s.indices(len(alpha)))
Out[29]: [5, 4]
หมายเหตุ:โพสต์นี้ถูกเขียนเดิมในบล็อกของฉันข่าวกรองเบื้องหลังหลามชิ้น
ตามกฎทั่วไปการเขียนโค้ดที่มีค่าดัชนี hardcoded จำนวนมากนำไปสู่ความไม่สะดวกในการอ่านและการบำรุงรักษา ตัวอย่างเช่นหากคุณกลับมาที่รหัสในอีกหนึ่งปีต่อมาคุณจะเห็นและสงสัยว่าคุณคิดอย่างไรเมื่อคุณเขียนมัน วิธีแก้ปัญหาที่แสดงเป็นเพียงวิธีการที่ชัดเจนยิ่งขึ้นว่ารหัสของคุณกำลังทำอะไรอยู่ โดยทั่วไป slice ในตัว () จะสร้างวัตถุชิ้นที่สามารถใช้ได้ทุกที่ที่ได้รับอนุญาต ตัวอย่างเช่น:
>>> items = [0, 1, 2, 3, 4, 5, 6]
>>> a = slice(2, 4)
>>> items[2:4]
[2, 3]
>>> items[a]
[2, 3]
>>> items[a] = [10,11]
>>> items
[0, 1, 10, 11, 4, 5, 6]
>>> del items[a]
>>> items
[0, 1, 4, 5, 6]
หากคุณมีอินสแตนซ์ส่วนแบ่ง s คุณสามารถรับข้อมูลเพิ่มเติมเกี่ยวกับมันได้โดยดูที่แอ็ตทริบิวต์ s.start, s.stop และ s.step ตัวอย่างเช่น:
>>> a = slice(10, 50, 2) >>> a.start 10 >>> a.stop 50 >>> a.step 2 >>>
เพื่อให้ง่ายขึ้นโปรดจำไว้ว่าslice มีรูปแบบเดียวเท่านั้น:
s[start:end:step]
และนี่คือวิธีการทำงาน:
s
: วัตถุที่สามารถหั่นได้start
: ดัชนีแรกเพื่อเริ่มการทำซ้ำend
: ดัชนีล่าสุดโปรดทราบว่าend
ดัชนีจะไม่รวมอยู่ในส่วนที่เป็นผลลัพธ์step
: เลือกองค์ประกอบทุกstep
ดัชนีสิ่งที่นำเข้าอื่น ๆ : ทั้งหมดstart
, end
, step
สามารถละเว้น! และถ้าพวกเขาจะถูกตัดออกค่าเริ่มต้นของพวกเขาจะถูกนำมาใช้: 0
, len(s)
, 1
ตาม
ดังนั้นรูปแบบที่เป็นไปได้คือ:
# Mostly used variations
s[start:end]
s[start:]
s[:end]
# Step-related variations
s[:end:step]
s[start::step]
s[::step]
# Make a copy
s[:]
หมายเหตุ: หากstart >= end
(พิจารณาเฉพาะเมื่อstep>0
) []
งูหลามจะกลับมาเป็นชิ้นที่ว่างเปล่า
ส่วนด้านบนจะอธิบายเกี่ยวกับคุณสมบัติหลักของชิ้นงานและมันจะทำงานในเกือบทุกครั้ง อย่างไรก็ตามอาจมีข้อผิดพลาดที่คุณควรระวังและส่วนนี้อธิบายถึงพวกเขา
สิ่งแรกที่สร้างความสับสนให้กับผู้เรียน Python คือดัชนีสามารถลบได้! อย่าตกใจ: ดัชนีลบหมายถึงนับถอยหลัง
ตัวอย่างเช่น:
s[-5:] # Start at the 5th index from the end of array,
# thus returning the last 5 elements.
s[:-5] # Start at index 0, and end until the 5th index from end of array,
# thus returning s[0:len(s)-5].
การทำให้สิ่งต่าง ๆ สับสนมากขึ้นนั่นstep
ก็อาจเป็นลบเช่นกัน!
ขั้นตอนเชิงลบหมายถึงวนซ้ำอาร์เรย์ไปข้างหลัง: ตั้งแต่ต้นจนจบโดยมีดัชนีสิ้นสุดรวมอยู่ด้วยและดัชนีเริ่มต้นไม่รวมอยู่ในผลลัพธ์
หมายเหตุ : เมื่อขั้นตอนเป็นลบค่าเริ่มต้นสำหรับstart
คือlen(s)
(ในขณะที่end
ไม่เท่ากับ0
เนื่องจากs[::-1]
มีs[0]
) ตัวอย่างเช่น:
s[::-1] # Reversed slice
s[len(s)::-1] # The same as above, reversed slice
s[0:len(s):-1] # Empty list
จะประหลาดใจ: ชิ้นจะไม่เพิ่ม IndexError เมื่อดัชนีอยู่นอกช่วง!
หากดัชนีอยู่นอกช่วง Python จะพยายามอย่างดีที่สุดเพื่อตั้งค่าดัชนีให้เป็น0
หรือlen(s)
ตามสถานการณ์ ตัวอย่างเช่น:
s[:len(s)+5] # The same as s[:len(s)]
s[-len(s)-5::] # The same as s[0:]
s[len(s)+5::-1] # The same as s[len(s)::-1], and the same as s[::-1]
ให้คำตอบนี้จบด้วยตัวอย่างอธิบายทุกสิ่งที่เราพูดถึง:
# Create our array for demonstration
In [1]: s = [i for i in range(10)]
In [2]: s
Out[2]: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
In [3]: s[2:] # From index 2 to last index
Out[3]: [2, 3, 4, 5, 6, 7, 8, 9]
In [4]: s[:8] # From index 0 up to index 8
Out[4]: [0, 1, 2, 3, 4, 5, 6, 7]
In [5]: s[4:7] # From index 4 (included) up to index 7(excluded)
Out[5]: [4, 5, 6]
In [6]: s[:-2] # Up to second last index (negative index)
Out[6]: [0, 1, 2, 3, 4, 5, 6, 7]
In [7]: s[-2:] # From second last index (negative index)
Out[7]: [8, 9]
In [8]: s[::-1] # From last to first in reverse order (negative step)
Out[8]: [9, 8, 7, 6, 5, 4, 3, 2, 1, 0]
In [9]: s[::-2] # All odd numbers in reversed order
Out[9]: [9, 7, 5, 3, 1]
In [11]: s[-2::-2] # All even numbers in reversed order
Out[11]: [8, 6, 4, 2, 0]
In [12]: s[3:15] # End is out of range, and Python will set it to len(s).
Out[12]: [3, 4, 5, 6, 7, 8, 9]
In [14]: s[5:1] # Start > end; return empty list
Out[14]: []
In [15]: s[11] # Access index 11 (greater than len(s)) will raise an IndexError
---------------------------------------------------------------------------
IndexError Traceback (most recent call last)
<ipython-input-15-79ffc22473a3> in <module>()
----> 1 s[11]
IndexError: list index out of range
คำตอบก่อนหน้านี้ไม่ได้พูดถึงการแบ่งส่วนข้อมูลแบบหลายมิติซึ่งเป็นไปได้โดยใช้แพ็คเกจNumPy ที่มีชื่อเสียง:
การแบ่งส่วนสามารถนำไปใช้กับอาร์เรย์หลายมิติได้
# Here, a is a NumPy array
>>> a
array([[ 1, 2, 3, 4],
[ 5, 6, 7, 8],
[ 9, 10, 11, 12]])
>>> a[:2, 0:3:2]
array([[1, 3],
[5, 7]])
" :2
" ก่อนเครื่องหมายจุลภาคจะทำงานในมิติแรกและ " 0:3:2
" หลังจากเครื่องหมายจุลภาคทำงานในมิติที่สอง
list
แต่เฉพาะarray
ใน Numpy
#!/usr/bin/env python
def slicegraphical(s, lista):
if len(s) > 9:
print """Enter a string of maximum 9 characters,
so the printig would looki nice"""
return 0;
# print " ",
print ' '+'+---' * len(s) +'+'
print ' ',
for letter in s:
print '| {}'.format(letter),
print '|'
print " ",; print '+---' * len(s) +'+'
print " ",
for letter in range(len(s) +1):
print '{} '.format(letter),
print ""
for letter in range(-1*(len(s)), 0):
print ' {}'.format(letter),
print ''
print ''
for triada in lista:
if len(triada) == 3:
if triada[0]==None and triada[1] == None and triada[2] == None:
# 000
print s+'[ : : ]' +' = ', s[triada[0]:triada[1]:triada[2]]
elif triada[0] == None and triada[1] == None and triada[2] != None:
# 001
print s+'[ : :{0:2d} ]'.format(triada[2], '','') +' = ', s[triada[0]:triada[1]:triada[2]]
elif triada[0] == None and triada[1] != None and triada[2] == None:
# 010
print s+'[ :{0:2d} : ]'.format(triada[1]) +' = ', s[triada[0]:triada[1]:triada[2]]
elif triada[0] == None and triada[1] != None and triada[2] != None:
# 011
print s+'[ :{0:2d} :{1:2d} ]'.format(triada[1], triada[2]) +' = ', s[triada[0]:triada[1]:triada[2]]
elif triada[0] != None and triada[1] == None and triada[2] == None:
# 100
print s+'[{0:2d} : : ]'.format(triada[0]) +' = ', s[triada[0]:triada[1]:triada[2]]
elif triada[0] != None and triada[1] == None and triada[2] != None:
# 101
print s+'[{0:2d} : :{1:2d} ]'.format(triada[0], triada[2]) +' = ', s[triada[0]:triada[1]:triada[2]]
elif triada[0] != None and triada[1] != None and triada[2] == None:
# 110
print s+'[{0:2d} :{1:2d} : ]'.format(triada[0], triada[1]) +' = ', s[triada[0]:triada[1]:triada[2]]
elif triada[0] != None and triada[1] != None and triada[2] != None:
# 111
print s+'[{0:2d} :{1:2d} :{2:2d} ]'.format(triada[0], triada[1], triada[2]) +' = ', s[triada[0]:triada[1]:triada[2]]
elif len(triada) == 2:
if triada[0] == None and triada[1] == None:
# 00
print s+'[ : ] ' + ' = ', s[triada[0]:triada[1]]
elif triada[0] == None and triada[1] != None:
# 01
print s+'[ :{0:2d} ] '.format(triada[1]) + ' = ', s[triada[0]:triada[1]]
elif triada[0] != None and triada[1] == None:
# 10
print s+'[{0:2d} : ] '.format(triada[0]) + ' = ', s[triada[0]:triada[1]]
elif triada[0] != None and triada[1] != None:
# 11
print s+'[{0:2d} :{1:2d} ] '.format(triada[0],triada[1]) + ' = ', s[triada[0]:triada[1]]
elif len(triada) == 1:
print s+'[{0:2d} ] '.format(triada[0]) + ' = ', s[triada[0]]
if __name__ == '__main__':
# Change "s" to what ever string you like, make it 9 characters for
# better representation.
s = 'COMPUTERS'
# add to this list different lists to experement with indexes
# to represent ex. s[::], use s[None, None,None], otherwise you get an error
# for s[2:] use s[2:None]
lista = [[4,7],[2,5,2],[-5,1,-1],[4],[-4,-6,-1], [2,-3,1],[2,-3,-1], [None,None,-1],[-5,None],[-5,0,-1],[-5,None,-1],[-1,1,-2]]
slicegraphical(s, lista)
คุณสามารถเรียกใช้สคริปต์นี้และทดลองกับมันด้านล่างนี้เป็นตัวอย่างบางส่วนที่ฉันได้รับจากสคริปต์
+---+---+---+---+---+---+---+---+---+
| C | O | M | P | U | T | E | R | S |
+---+---+---+---+---+---+---+---+---+
0 1 2 3 4 5 6 7 8 9
-9 -8 -7 -6 -5 -4 -3 -2 -1
COMPUTERS[ 4 : 7 ] = UTE
COMPUTERS[ 2 : 5 : 2 ] = MU
COMPUTERS[-5 : 1 :-1 ] = UPM
COMPUTERS[ 4 ] = U
COMPUTERS[-4 :-6 :-1 ] = TU
COMPUTERS[ 2 :-3 : 1 ] = MPUT
COMPUTERS[ 2 :-3 :-1 ] =
COMPUTERS[ : :-1 ] = SRETUPMOC
COMPUTERS[-5 : ] = UTERS
COMPUTERS[-5 : 0 :-1 ] = UPMO
COMPUTERS[-5 : :-1 ] = UPMOC
COMPUTERS[-1 : 1 :-2 ] = SEUM
[Finished in 0.9s]
เมื่อใช้ขั้นตอนเชิงลบให้สังเกตว่าคำตอบถูกเลื่อนไปทางขวา 1
สมองของฉันดูเหมือนจะมีความสุขที่จะยอมรับว่าlst[start:end]
มีstart
รายการ -th ฉันอาจจะบอกว่ามันเป็น 'ข้อสันนิษฐานตามธรรมชาติ'
แต่ในบางครั้งมีข้อสงสัยเกิดขึ้นและสมองของฉันขอความมั่นใจว่าไม่มีend
องค์ประกอบ -th
ในช่วงเวลาเหล่านี้ฉันพึ่งพาทฤษฎีบทง่ายๆนี้:
for any n, lst = lst[:n] + lst[n:]
คุณสมบัตินี้สวยบอกว่าlst[start:end]
ไม่ได้มีend
รายการ -th lst[end:]
เพราะมันอยู่ใน
โปรดทราบว่าทฤษฎีบทนี้เป็นจริงสำหรับn
ทุก ๆ ตัวอย่างเช่นคุณสามารถตรวจสอบได้
lst = range(10)
lst[:-42] + lst[-42:] == lst
True
ผลตอบแทน
ในความคิดของฉันคุณจะเข้าใจและจดจำเครื่องหมาย Python ของการแบ่งสตริงได้ดียิ่งขึ้นหากคุณดูด้วยวิธีดังต่อไปนี้ (อ่านต่อ)
มาทำงานกับสตริงต่อไปนี้ ...
azString = "abcdefghijklmnopqrstuvwxyz"
สำหรับผู้ที่ไม่ทราบคุณสามารถสร้างสตริงย่อยจากการazString
ใช้สัญลักษณ์azString[x:y]
มาจากภาษาโปรแกรมอื่น ๆ นั่นคือเมื่อสามัญสำนึกได้รับความเสียหาย x และ y คืออะไร
ฉันต้องนั่งลงและเรียกใช้หลายสถานการณ์ในการค้นหาเทคนิคการท่องจำที่จะช่วยให้ฉันจำได้ว่า x และ y คืออะไรและช่วยให้ฉันฝานสตริงอย่างถูกต้องตั้งแต่ครั้งแรก
ข้อสรุปของฉันคือ x และ y ควรถูกมองว่าเป็นดัชนีขอบเขตที่ล้อมรอบสตริงที่เราต้องการเพิ่ม ดังนั้นเราควรจะเห็นการแสดงออกเป็นหรือมากขึ้นชัดเจนเป็นazString[index1, index2]
azString[index_of_first_character, index_after_the_last_character]
นี่คือตัวอย่างการสร้างภาพข้อมูล ...
Letters a b c d e f g h i j ...
↑ ↑ ↑ ↑ ↑ ↑ ↑ ↑ ↑ ↑
┊ ┊
Indexes 0 1 2 3 4 5 6 7 8 9 ...
┊ ┊
cdefgh index1 index2
ดังนั้นสิ่งที่คุณต้องทำคือการตั้งค่า index1 และ index2 เป็นค่าที่ล้อมรอบซับสตริงที่ต้องการ ตัวอย่างเช่นในการรับสตริงย่อย "cdefgh" คุณสามารถใช้azString[2:8]
เพราะดัชนีทางด้านซ้ายของ "c" คือ 2 และหนึ่งในขนาดที่เหมาะสมของ "h" คือ 8
จำไว้ว่าเรากำลังกำหนดขอบเขต และขอบเขตเหล่านั้นคือตำแหน่งที่คุณสามารถวางวงเล็บที่จะพันรอบสตริงย่อยแบบนี้ ...
ab [ cdefgh ] ij
เคล็ดลับนั้นใช้ได้ตลอดเวลาและง่ายต่อการจดจำ
คำตอบก่อนหน้านี้ส่วนใหญ่ล้างคำถามเกี่ยวกับสัญกรณ์สไลซ์
ไวยากรณ์การจัดทำดัชนีเพิ่มเติมที่ใช้สำหรับการแบ่งเป็นaList[start:stop:step]
และตัวอย่างพื้นฐานคือ:
ตัวอย่างการตัดเพิ่มเติม: 15 ส่วนเพิ่มเติม
ใน Python รูปแบบพื้นฐานที่สุดสำหรับการแบ่งเป็นดังนี้:
l[start:end]
โดยที่l
มีการรวบรวมstart
เป็นดัชนีรวมและend
เป็นดัชนีพิเศษ
In [1]: l = list(range(10))
In [2]: l[:5] # First five elements
Out[2]: [0, 1, 2, 3, 4]
In [3]: l[-5:] # Last five elements
Out[3]: [5, 6, 7, 8, 9]
เมื่อตัดจากจุดเริ่มต้นคุณสามารถละเว้นดัชนีเป็นศูนย์และเมื่อแบ่งเป็นจุดสิ้นสุดคุณสามารถละเว้นดัชนีสุดท้ายเนื่องจากซ้ำซ้อนจึงไม่ต้อง verbose:
In [5]: l[:3] == l[0:3]
Out[5]: True
In [6]: l[7:] == l[7:len(l)]
Out[6]: True
จำนวนเต็มลบมีประโยชน์เมื่อทำการชดเชยที่สัมพันธ์กับจุดสิ้นสุดของการรวบรวม:
In [7]: l[:-1] # Include all elements but the last one
Out[7]: [0, 1, 2, 3, 4, 5, 6, 7, 8]
In [8]: l[-3:] # Take the last three elements
Out[8]: [7, 8, 9]
เป็นไปได้ที่จะให้ดัชนีที่อยู่นอกขอบเขตเมื่อมีการแบ่งส่วนเช่น:
In [9]: l[:20] # 20 is out of index bounds, and l[20] will raise an IndexError exception
Out[9]: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
In [11]: l[-20:] # -20 is out of index bounds, and l[-20] will raise an IndexError exception
Out[11]: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
โปรดทราบว่าผลลัพธ์ของการแบ่งคอลเล็กชันเป็นคอลเล็กชันใหม่ทั้งหมด นอกจากนี้เมื่อใช้สัญกรณ์ชิ้นในการกำหนดความยาวของการกำหนดชิ้นไม่จำเป็นต้องเหมือนกัน ค่าก่อนและหลังชิ้นที่ได้รับมอบหมายจะถูกเก็บไว้และการรวบรวมจะลดขนาดหรือขยายเพื่อให้มีค่าใหม่:
In [16]: l[2:6] = list('abc') # Assigning fewer elements than the ones contained in the sliced collection l[2:6]
In [17]: l
Out[17]: [0, 1, 'a', 'b', 'c', 6, 7, 8, 9]
In [18]: l[2:5] = list('hello') # Assigning more elements than the ones contained in the sliced collection l [2:5]
In [19]: l
Out[19]: [0, 1, 'h', 'e', 'l', 'l', 'o', 6, 7, 8, 9]
หากคุณไม่ใช้ดัชนีเริ่มต้นและสิ้นสุดคุณจะทำสำเนาของคอลเล็กชัน:
In [14]: l_copy = l[:]
In [15]: l == l_copy and l is not l_copy
Out[15]: True
หากละเว้นดัชนีเริ่มต้นและสิ้นสุดเมื่อดำเนินการกำหนดเนื้อหาทั้งหมดของคอลเลกชันจะถูกแทนที่ด้วยสำเนาของสิ่งที่อ้างอิง:
In [20]: l[:] = list('hello...')
In [21]: l
Out[21]: ['h', 'e', 'l', 'l', 'o', '.', '.', '.']
นอกจากการแบ่งส่วนพื้นฐานแล้วยังสามารถใช้สัญลักษณ์ต่อไปนี้:
l[start:end:step]
โดยที่l
คือคอลเล็กชันstart
เป็นดัชนีแบบรวมend
เป็นดัชนีพิเศษและstep
เป็นขั้นตอนที่สามารถใช้เพื่อนำทุกรายการที่nเข้าl
มา
In [22]: l = list(range(10))
In [23]: l[::2] # Take the elements which indexes are even
Out[23]: [0, 2, 4, 6, 8]
In [24]: l[1::2] # Take the elements which indexes are odd
Out[24]: [1, 3, 5, 7, 9]
การใช้step
เป็นเคล็ดลับที่มีประโยชน์ในการเก็บรวบรวมย้อนกลับใน Python:
In [25]: l[::-1]
Out[25]: [9, 8, 7, 6, 5, 4, 3, 2, 1, 0]
นอกจากนี้ยังเป็นไปได้ที่จะใช้จำนวนเต็มลบเพื่อstep
เป็นตัวอย่างต่อไปนี้:
In[28]: l[::-2]
Out[28]: [9, 7, 5, 3, 1]
อย่างไรก็ตามการใช้ค่าลบสำหรับstep
อาจทำให้สับสนมาก นอกจากนี้ในการที่จะPythonicคุณควรหลีกเลี่ยงการใช้start
, end
และstep
ในชิ้นเดียว ในกรณีนี้จำเป็นต้องพิจารณาการทำเช่นนี้ในสองงานที่ได้รับมอบหมาย (หนึ่งไปยังชิ้นและอื่น ๆ ที่จะก้าว)
In [29]: l = l[::2] # This step is for striding
In [30]: l
Out[30]: [0, 2, 4, 6, 8]
In [31]: l = l[1:-1] # This step is for slicing
In [32]: l
Out[32]: [2, 4, 6]
ฉันต้องการเพิ่มHello, World! ตัวอย่างที่อธิบายพื้นฐานของสไลซ์สำหรับผู้เริ่มต้น มันช่วยฉันได้มาก
มีรายการที่มีค่าหกค่า['P', 'Y', 'T', 'H', 'O', 'N']
:
+---+---+---+---+---+---+
| P | Y | T | H | O | N |
+---+---+---+---+---+---+
0 1 2 3 4 5
ตอนนี้ส่วนที่ง่ายที่สุดของรายการนั้นคือรายการย่อย สัญกรณ์คือ[<index>:<index>]
และที่สำคัญคือการอ่านมันเช่นนี้:
[ start cutting before this index : end cutting before this index ]
ตอนนี้ถ้าคุณทำ[2:5]
รายการด้านบนนี้จะเกิดขึ้น:
| |
+---+---|---+---+---|---+
| P | Y | T | H | O | N |
+---+---|---+---+---|---+
0 1 | 2 3 4 | 5
คุณได้ทำการตัดก่อนองค์ประกอบดัชนี2
และตัดอีกก่อน5
องค์ประกอบที่มีค่าดัชนี ['T', 'H', 'O']
ดังนั้นผลจะเป็นชิ้นระหว่างทั้งสองตัดเป็นรายการ
โดยส่วนตัวฉันคิดว่ามันเหมือนfor
วน:
a[start:end:step]
# for(i = start; i < end; i += step)
นอกจากนี้ทราบว่าค่าลบสำหรับstart
และเป็นญาติกับส่วนท้ายของรายการและคำนวณได้ในตัวอย่างข้างต้นโดยend
given_index + a.shape[0]
ด้านล่างเป็นตัวอย่างของดัชนีของสตริง:
+---+---+---+---+---+
| H | e | l | p | A |
+---+---+---+---+---+
0 1 2 3 4 5
-5 -4 -3 -2 -1
str="Name string"
ตัวอย่างการแบ่งส่วน: [start: end: step]
str[start:end] # Items start through end-1
str[start:] # Items start through the rest of the array
str[:end] # Items from the beginning through end-1
str[:] # A copy of the whole array
ด้านล่างคือตัวอย่างการใช้งาน:
print str[0] = N
print str[0:2] = Na
print str[0:7] = Name st
print str[0:7:2] = Nm t
print str[0:-1:2] = Nm ti
len - index
ถ้าคุณรู้สึกว่าดัชนีติดลบในหั่นเป็นความสับสนที่นี่เป็นวิธีที่ง่ายมากที่จะคิดเกี่ยวกับมันเพียงแค่เปลี่ยนดัชนีเชิงลบด้วย len(list) - 3
ดังนั้นสำหรับตัวอย่างเช่นแทนที่ด้วย -3
วิธีที่ดีที่สุดในการแสดงให้เห็นว่าการแบ่งส่วนข้อมูลใดภายในเป็นการแสดงในโค้ดที่ใช้การดำเนินการนี้:
def slice(list, start = None, end = None, step = 1):
# Take care of missing start/end parameters
start = 0 if start is None else start
end = len(list) if end is None else end
# Take care of negative start/end parameters
start = len(list) + start if start < 0 else start
end = len(list) + end if end < 0 else end
# Now just execute a for-loop with start, end and step
return [list[i] for i in range(start, end, step)]
เทคนิคการแบ่งขั้นพื้นฐานคือการกำหนดจุดเริ่มต้นจุดหยุดและขนาดขั้นตอน - หรือที่เรียกว่าก้าวย่าง
ก่อนอื่นเราจะสร้างรายการค่าที่จะใช้ในการแบ่งส่วนของเรา
สร้างสองรายการเพื่อแบ่ง รายการแรกคือรายการตัวเลขตั้งแต่ 1 ถึง 9 (รายการ A) รายการที่สองเป็นรายการตัวเลขตั้งแต่ 0 ถึง 9 (รายการ B):
A = list(range(1, 10, 1)) # Start, stop, and step
B = list(range(9))
print("This is List A:", A)
print("This is List B:", B)
ทำดัชนีหมายเลข 3 จาก A และหมายเลข 6 จาก B
print(A[2])
print(B[6])
การแบ่งขั้นพื้นฐาน
ไวยากรณ์การจัดทำดัชนีเพิ่มเติมที่ใช้สำหรับการแบ่งเป็น aList [start: stop: step] อาร์กิวเมนต์เริ่มต้นและอาร์กิวเมนต์ขั้นตอนทั้งคู่ไม่มีค่าเริ่มต้น - อาร์กิวเมนต์ที่จำเป็นเท่านั้นคือหยุด คุณสังเกตเห็นว่าสิ่งนี้คล้ายคลึงกับช่วงที่ใช้ในการกำหนดรายการ A และ B หรือไม่ นี่เป็นเพราะวัตถุชิ้นแสดงชุดของดัชนีที่ระบุโดยช่วง (เริ่มหยุดขั้นตอน) เอกสาร Python 3.4
อย่างที่คุณเห็นการกำหนดหยุดเพียงแค่คืนค่าองค์ประกอบเดียว ตั้งแต่เริ่มต้นเริ่มต้นที่ไม่มีสิ่งนี้แปลเป็นการดึงองค์ประกอบเดียวเท่านั้น
มันเป็นสิ่งสำคัญที่จะต้องทราบองค์ประกอบแรกคือดัชนี 0 ไม่ใช่ดัชนี 1 นี่คือเหตุผลที่เราใช้ 2 รายการสำหรับการออกกำลังกายนี้ องค์ประกอบของรายการ A จะถูกกำหนดหมายเลขตามตำแหน่งอันดับ (องค์ประกอบแรกคือ 1 องค์ประกอบที่สองคือ 2 ฯลฯ ) ในขณะที่องค์ประกอบรายการของ B คือตัวเลขที่จะใช้ในการทำดัชนีองค์ประกอบเหล่านั้น ([0] สำหรับองค์ประกอบแรก 0 ฯลฯ )
ด้วยไวยากรณ์การจัดทำดัชนีแบบขยายเราเรียกช่วงของค่า ตัวอย่างเช่นค่าทั้งหมดจะถูกดึงด้วยโคลอน
A[:]
ในการเรียกชุดย่อยขององค์ประกอบจำเป็นต้องกำหนดตำแหน่งเริ่มต้นและหยุด
รับรูปแบบ aList [start: stop] ดึงสององค์ประกอบแรกจากรายการ A
ฉันไม่คิดว่าPython tutorial diagram (อ้างถึงในคำตอบอื่น ๆ อีกมากมาย) นั้นดีเพราะคำแนะนำนี้ใช้ได้กับการก้าวย่างที่ดี แต่ไม่เหมาะสำหรับการก้าวเดินเชิงลบ
นี่คือแผนภาพ:
+---+---+---+---+---+---+
| P | y | t | h | o | n |
+---+---+---+---+---+---+
0 1 2 3 4 5 6
-6 -5 -4 -3 -2 -1
จากแผนภาพที่ผมคาดหวังว่าa[-4,-6,-1]
จะเป็นแต่มันเป็นyP
ty
>>> a = "Python"
>>> a[2:4:1] # as expected
'th'
>>> a[-4:-6:-1] # off by 1
'ty'
สิ่งที่ใช้งานได้เสมอคือคิดเป็นตัวละครหรือสล็อตและใช้การจัดทำดัชนีเป็นช่วงเวลาครึ่งเปิด - เปิดด้านขวาถ้าก้าวบวก, เปิดซ้ายถ้าก้าวย่างเชิงลบ
ด้วยวิธีนี้ฉันสามารถคิดa[-4:-6:-1]
เป็นa(-6,-4]
ในคำศัพท์ช่วงเวลา
+---+---+---+---+---+---+
| P | y | t | h | o | n |
+---+---+---+---+---+---+
0 1 2 3 4 5
-6 -5 -4 -3 -2 -1
+---+---+---+---+---+---+---+---+---+---+---+---+
| P | y | t | h | o | n | P | y | t | h | o | n |
+---+---+---+---+---+---+---+---+---+---+---+---+
-6 -5 -4 -3 -2 -1 0 1 2 3 4 5