พิมพ์รายการในลำดับย้อนกลับที่มีช่วง () หรือไม่


364

คุณจะสร้างรายการต่อไปนี้range()ใน Python ได้อย่างไร?

[9, 8, 7, 6, 5, 4, 3, 2, 1, 0]

สิ่งที่เกี่ยวกับ [* ช่วง (9, -1, -1)]? pythonic สุดยอด!
onofricamila

คำตอบ:


561

ใช้reversed()ฟังก์ชั่น:

reversed(range(10))

มันมีความหมายมากกว่านี้มาก

ปรับปรุง:

หากคุณต้องการให้เป็นรายการ (ตามที่ btk ชี้ให้เห็น):

list(reversed(range(10)))

ปรับปรุง:

หากคุณต้องการใช้เพียงrangeเพื่อให้ได้ผลลัพธ์เดียวกันคุณสามารถใช้พารามิเตอร์ทั้งหมดได้range(start, stop, step)

ตัวอย่างเช่นในการสร้างรายการ[5,4,3,2,1,0]คุณสามารถใช้รายการต่อไปนี้:

range(5, -1, -1)

มันอาจจะใช้งานง่ายน้อยลง แต่เป็นความคิดเห็นที่กล่าวถึงนี้มีประสิทธิภาพมากขึ้นและการใช้งานที่ถูกต้องของช่วงสำหรับรายการที่กลับรายการ


13
แม้ว่ามันจะ 'มีประสิทธิภาพน้อยกว่า และคุณไม่สามารถทำการแบ่งส่วนข้อมูลได้
Jakob Bowyer

6
คำตอบนี้เป็นอย่างมากที่ชัดเจนและเข้าใจง่าย แต่มันจะต้องไม่range(10) range(9)นอกจากนี้ถ้าคุณต้องการให้รายการเต็มรูปแบบ (สำหรับหั่น ฯลฯ ) list(reversed(range(10)))ที่คุณควรทำ
John Y

5
สิ่งนี้สร้างตัววนซ้ำ OP ขอผลลัพธ์ในรูปแบบของรายการ
btk

6
การใช้ "reverse" กับเครื่องกำเนิด python (สมมติว่าเราพูดถึง Python 3 ในตัว) เป็นเพียงแนวคิดที่ผิดและสอนนิสัยที่ไม่ถูกต้องโดยไม่คำนึงถึงความซับซ้อนของหน่วยความจำ / การประมวลผลเมื่อเขียนโปรแกรมในภาษาระดับสูง
thedk

7
ใน Python3, reversedไม่รับเครื่องกำเนิดไฟฟ้าโดยทั่วไป rangeแต่ก็ยอมรับ เหตุใดจึงreversed(range(10000))ต้องจัดสรรหน่วยความจำสำหรับรายการทั้งหมด rangeสามารถส่งคืนวัตถุที่ใช้__reversed__วิธีการที่อนุญาตให้ทำซ้ำย้อนกลับที่มีประสิทธิภาพได้หรือไม่?
avmohan

312

ใช้ฟังก์ชันในตัว 'ช่วง' range(start, stop, step)ลายเซ็นคือ นี้ผลิตลำดับที่ทำให้ตัวเลขเริ่มต้นด้วยstartและสิ้นสุดถ้าได้รับถึงไม่รวมstopstop

>>> range(9,-1,-1)   
    [9, 8, 7, 6, 5, 4, 3, 2, 1, 0]
>>> range(-2, 6, 2)
    [-2, 0, 2, 4]

ใน Python 3 สิ่งนี้จะสร้างrangeอ็อบเจกต์ที่ไม่ใช่ลิสต์ซึ่งทำหน้าที่ได้อย่างมีประสิทธิภาพเหมือนกับลิสต์แบบอ่านอย่างเดียว (แต่ใช้หน่วยความจำน้อยกว่าโดยเฉพาะช่วงที่มีขนาดใหญ่)


1
คุณช่วยอธิบายสิ่งนี้ได้เช่นกันนอกจากนี้คุณยังสามารถแนะนำเว็บไซต์ / หนังสือ pdf สำหรับ python ให้ฉันได้ไหม
ramesh.mimit

8
@ramesh หากคุณใช้งานhelp(range)ใน python shell มันจะบอกคุณถึงข้อโต้แย้ง พวกเขาเป็นหมายเลขที่จะเริ่มต้นจำนวนที่จะสิ้นสุด (พิเศษ) และขั้นตอนที่จะดำเนินการดังนั้นจึงเริ่มที่ 9 และลบ 1 จนกว่าจะได้รับถึง -1 (ณ จุดที่มันหยุดโดยไม่กลับมาซึ่งเป็นเหตุผล ช่วงสิ้นสุดที่ 0)
Michael Mrozek

3
@ ramesh.mimit: เพียงไปที่เว็บไซต์ Python อย่างเป็นทางการ มีเอกสารฉบับเต็มอยู่ที่นั่นรวมถึงบทช่วยสอนที่ดี
John Y

5
จริง ๆ นี่คือคำตอบที่เหมาะสม แต่อาจอธิบายได้ชัดเจนยิ่งขึ้น range(start, stop, step) - เริ่มจากตัวเลขstartและให้ผลลัพธ์เว้นแต่จะstopได้มาถึงเคลื่อนย้ายโดยstepแต่ละครั้ง
นาย B

43

คุณสามารถใช้range(10)[::-1]ซึ่งเป็นสิ่งเดียวกันrange(9, -1, -1)และอ่านได้ง่ายขึ้น (ถ้าคุณคุ้นเคยกับsequence[::-1]สำนวน Python ทั่วไป)


28

สำหรับผู้ที่สนใจใน "ประสิทธิภาพ" ของตัวเลือกที่รวบรวมจนถึง ...

คำตอบของ Jaime RGPทำให้ฉันรีสตาร์ทคอมพิวเตอร์หลังจากกำหนดเวลาโซลูชันที่ "ท้าทาย" ของJason อย่างแท้จริงตามคำแนะนำของฉัน (ผ่านความคิดเห็น) เพื่อสำรองความอยากรู้อยากเห็นของคุณเกี่ยวกับการหยุดทำงานฉันนำเสนอผลลัพธ์ของฉันที่นี่ (แย่ที่สุด - ก่อน):

คำตอบของ Jason (อาจเป็นเพียงแค่การใช้พลังของความเข้าใจในรายการ ):

$ python -m timeit "[9-i for i in range(10)]"
1000000 loops, best of 3: 1.54 usec per loop

คำตอบของ martineau (อ่านได้ถ้าคุณคุ้นเคยกับไวยากรณ์ส่วนขยาย ):

$ python -m timeit "range(10)[::-1]"
1000000 loops, best of 3: 0.743 usec per loop

คำตอบของMichałŠrajer (ผู้ที่ได้รับการยอมรับอ่านง่ายมาก):

$ python -m timeit "reversed(range(10))"
1000000 loops, best of 3: 0.538 usec per loop

คำตอบของ bene (ครั้งแรก แต่ร่างมากในเวลานั้น ):

$ python -m timeit "range(9,-1,-1)"
1000000 loops, best of 3: 0.401 usec per loop

ตัวเลือกสุดท้ายที่ง่ายต่อการจำโดยใช้range(n-1,-1,-1)สัญกรณ์โดยVal Neekman


3
ฉันทำเวลาของตัวเองก่อนที่จะอ่านคำตอบนี้และได้ผลลัพธ์เดียวกัน
Todd Owen

13
for i in range(8, 0, -1)

จะแก้ปัญหานี้ มันจะออก 8 ถึง 1 และ -1 หมายถึงรายการที่กลับรายการ


10

ไม่มีเหตุผลที่จะใช้reverseเนื่องจากวิธีช่วงสามารถส่งคืนรายการที่กลับรายการได้

เมื่อคุณมีการวนซ้ำมากกว่าnรายการและต้องการแทนที่ลำดับของรายการที่ส่งคืนโดยrange(start, stop, step)คุณต้องใช้พารามิเตอร์ช่วงที่สามซึ่งระบุstepและตั้งค่าเป็น-1พารามิเตอร์อื่น ๆ จะถูกปรับตาม:

  1. ให้หยุดพารามิเตอร์-1(มันคุ้มค่าก่อนหน้านี้stop - 1, stopเท่ากับ0)
  2. n-1ขณะที่การใช้พารามิเตอร์เริ่มต้น

ดังนั้นช่วงที่เทียบเท่า (n) ในลำดับย้อนกลับจะเป็น:

n = 10
print range(n-1,-1,-1) 
#[9, 8, 7, 6, 5, 4, 3, 2, 1, 0]

6
ตรงไปตรงมาฉันพบว่ามันใช้งานง่ายกว่าreversed(range(n))
Nicholas Hamilton

1
@NicholasHamilton เห็นด้วยกับคุณอย่างไรก็ตามความคิดที่อยู่เบื้องหลังคำตอบนั้นคือการใช้ทรัพยากรให้น้อยลง ... (และคำถามเกี่ยวกับการใช้ฟังก์ชั่นการทำงานแบบช่วง :))
Andriy Ivaneyko

ตกลงไม่เป็นไรฉันคิดว่ามันขึ้นอยู่กับสถานการณ์ ตัวอย่างเช่นหากใช้ฟังก์ชันช่วงเป็นดัชนีสำหรับการวนซ้ำมันจะมีผล จำกัด อย่างไรก็ตามหากใช้ภายในวงภายนอกค่าใช้จ่ายจะเพิ่ม ...
Nicholas Hamilton

8

readibility กันดูเหมือนว่าจะเร็วกว่าreversed(range(n))range(n)[::-1]

$ python -m timeit "reversed(range(1000000000))"
1000000 loops, best of 3: 0.598 usec per loop
$ python -m timeit "range(1000000000)[::-1]"
1000000 loops, best of 3: 0.945 usec per loop

เพียงแค่มีคนสงสัยว่า :)


ดีที่มีบางหมายเลข :) - ทำไมคุณไม่เพิ่มrange(1000000000-1,-1,-1)ด้วย?
Wolf

... ดีกว่าอย่าลองtimeit range(1000000000-1,-1,-1)ใช้บรรทัดคำสั่งแทนที่จะดูผลลัพธ์ของฉัน :-)
Wolf

6

ข้อกำหนดในคำถามนี้ต้องการlistจำนวนเต็ม 10 ขนาดตามลำดับจากมากไปน้อย ดังนั้นมาสร้างรายการในไพ ธ อน

# This meets the requirement.
# But it is a bit harder to wrap one's head around this. right?
>>> range(10-1, -1, -1)
[9, 8, 7, 6, 5, 4, 3, 2, 1, 0]

# let's find something that is a bit more self-explanatory. Sounds good?
# ----------------------------------------------------

# This returns a list in ascending order.
# Opposite of what the requirement called for.
>>> range(10)
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

# This returns an iterator in descending order.
# Doesn't meet the requirement as it is not a list.
>>> reversed(range(10))
<listreverseiterator object at 0x10e14e090>

# This returns a list in descending order and meets the requirement
>>> list(reversed(range(10)))
[9, 8, 7, 6, 5, 4, 3, 2, 1, 0]

2
ฉันชอบทริปเปิลมาก-1มันเป็นรูปแบบนี้ที่ทำให้ง่ายต่อการรักษาwrap one's head around this- วันนี้ฉันเรียนรู้ว่าถ้าต้องมีประสิทธิภาพจริงๆให้ใช้range(n-1, -1, -1)เมื่อสำรวจช่วงในลำดับที่กลับด้าน
Wolf

5

คุณสามารถพิมพ์ตัวเลขย้อนกลับด้วย range () BIF Like,

for number in range ( 10 , 0 , -1 ) :
    print ( number ) 

ผลผลิตจะเป็น [10,9,8,7,6,5,4,3,2,1]

range () - range (start, end, increment / decrement) โดยที่ start รวม, end เป็นเอกสิทธิ์และการเพิ่มขึ้นสามารถเป็นตัวเลขใด ๆ และพฤติกรรมเช่นขั้นตอน


5

คำถามที่ถามบ่อยมากว่าrange(9, -1, -1)ดีกว่าreversed(range(10))ใน Python 3 หรือไม่ ผู้ที่ทำงานในภาษาอื่นด้วยตัววนซ้ำในทันทีมีแนวโน้มที่จะคิดว่าการย้อนกลับ () ต้องแคชค่าทั้งหมดแล้วส่งกลับในลำดับย้อนกลับ สิ่งนี้คือreversed()ตัวดำเนินการของ Python ไม่ทำงานหากวัตถุเป็นเพียงตัววนซ้ำ วัตถุต้องมีหนึ่งในสองด้านล่างเพื่อให้ reverse () ทำงาน:

  1. ทั้งการสนับสนุนlen()และดัชนีจำนวนเต็มผ่าน[]
  2. หรือมี__reversed__()วิธีดำเนินการ

หากคุณพยายามที่จะใช้ reverse () บนวัตถุที่ไม่มีสิ่งใดข้างต้นคุณจะได้รับ:

>>> [reversed((x for x in range(10)))]
TypeError: 'generator' object is not reversible

ดังนั้นในระยะสั้นไพ ธ อนreversed()จึงมีความหมายเฉพาะกับอาเรย์เหมือนกับวัตถุดังนั้นมันควรมีประสิทธิภาพเช่นเดียวกับการทำซ้ำไปข้างหน้า

แต่เกี่ยวกับrange()อะไร นั่นไม่ใช่เครื่องกำเนิดไฟฟ้าใช่ไหม ใน Python 3 เป็นเครื่องกำเนิดไฟฟ้า แต่ถูกห่อในคลาสที่ใช้ทั้งสองอย่าง ดังนั้นrange(100000)ไม่ใช้หน่วยความจำมาก แต่ก็ยังรองรับการทำดัชนีและย้อนกลับที่มีประสิทธิภาพ

ดังนั้นโดยสรุปคุณสามารถใช้งานได้reversed(range(10))โดยไม่กระทบต่อประสิทธิภาพ


3

ฉันเชื่อว่านี่จะช่วยได้

range(5)[::-1]

ด้านล่างคือการใช้งาน:

for i in range(5)[::-1]:
    print i 

3
range(9,-1,-1)
[9, 8, 7, 6, 5, 4, 3, 2, 1, 0]

13
คำตอบของคุณแสดงว่าทำไมถึงreversed(range(10))เกิดข้อผิดพลาดน้อยกว่า ไม่มีความผิด Asinox เพียงแค่การสังเกตอย่างซื่อสัตย์
MichałŠrajer

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

3
@ ไซน์, ไม่เพียงแค่ปล่อยให้มันและสงสัยว่ามันสะสม 3 upvotes ... ฉันคิดว่าคุณสามารถตั้งค่าสถานะสำหรับความสนใจของผู้ดูแล (ซ้ำกันของคำตอบจาก 18 เดือนก่อนหน้านี้ยกเว้นเสีย) ไม่แน่ใจว่าพวกเขาจะลบมัน
OGHaza

สำหรับการอ้างอิงในอนาคตทั้งหมด: รหัสเท่านั้นไม่ใช่ VLQและคำตอบที่ไม่ถูกต้องไม่ควรถูกตั้งค่าสถานะเช่นกัน Downvote และไปต่อ แต่การตั้งค่าสถานะผิดในกรณีนี้ไม่ว่าจะเป็น NAA หรือ mod-flagging - จากการรีวิว
โซอี้

2

ใช้โดยไม่ต้อง [:: - 1] หรือกลับรายการ -

def reverse(text):
    result = []
    for index in range(len(text)-1,-1,-1):
        c = text[index]
        result.append(c)
    return ''.join(result)

print reverse("python!")

6
ทำไมคนควรจะเขียนนี้แทน"python!"[::-1]?
แดเนียล


1

คุณไม่จำเป็นต้องใช้ฟังก์ชันช่วงคุณสามารถทำรายการ [:: - 1] ซึ่งควรส่งคืนรายการในลำดับที่กลับรายการอย่างรวดเร็วโดยไม่ต้องใช้ส่วนเพิ่มเติมใด ๆ


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

1

สมมติว่าคุณมีรายการเรียกมันว่า a = {1,2,3,4,5} ตอนนี้ถ้าคุณต้องการพิมพ์รายการในสิ่งที่ตรงกันข้ามจากนั้นใช้รหัสต่อไปนี้

a.reverse
for i in a:
   print(i)

ฉันรู้ว่าคุณถามโดยใช้ช่วง แต่มันตอบแล้ว


0
range(9,-1,-1)
    [9, 8, 7, 6, 5, 4, 3, 2, 1, 0]

เป็นรูปแบบที่ถูกต้อง ถ้าคุณใช้

reversed(range(10))

คุณจะไม่ได้รับกรณี 0 ตัวอย่างเช่นสมมติว่า 10 ไม่ใช่หมายเลขเวทมนต์และตัวแปรที่คุณใช้ในการค้นหาเริ่มจากย้อนกลับ หากกรณีของคุณเป็น 0 การย้อนกลับ (ช่วง (0)) จะไม่ดำเนินการซึ่งผิดถ้าคุณบังเอิญมีวัตถุหนึ่งชิ้นในดัชนีศูนย์


0

ฉันคิดว่าหลายคน (ในฐานะตัวเอง) อาจสนใจในกรณีทั่วไปของการสำรวจรายการที่มีอยู่ในลำดับที่กลับรายการแทนตามที่ระบุไว้ในชื่อแทนที่จะสร้างดัชนีสำหรับการสำรวจเส้นทางดังกล่าว

แม้ว่าคำตอบที่ถูกต้องทั้งหมดยังคงสมบูรณ์แบบสำหรับกรณีนี้ฉันต้องการชี้ให้เห็นว่าการเปรียบเทียบประสิทธิภาพที่ทำในคำตอบของ Wolfมีไว้สำหรับสร้างดัชนีเท่านั้น ดังนั้นฉันจึงสร้างมาตรฐานที่คล้ายคลึงกันสำหรับการสำรวจรายการที่มีอยู่ในลำดับที่กลับรายการ

TL; DR a[::-1]เร็วที่สุด

วิชาบังคับก่อน:

a = list(range(10))

คำตอบของเจสัน :

%timeit [a[9-i] for i in range(10)]
1.27 µs ± 61.5 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each)

คำตอบของ martineau :

%timeit a[::-1]
135 ns ± 4.07 ns per loop (mean ± std. dev. of 7 runs, 10000000 loops each)

คำตอบของMichałŠrajer :

%timeit list(reversed(a))
374 ns ± 9.87 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each)

คำตอบของ bene :

%timeit [a[i] for i in range(9, -1, -1)]
1.09 µs ± 11.1 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each)

อย่างที่คุณเห็นในกรณีนี้ไม่จำเป็นต้องสร้างดัชนีอย่างชัดเจนดังนั้นวิธีที่เร็วที่สุดคือวิธีที่ทำให้การดำเนินการพิเศษน้อยลง

หมายเหตุ: ผมทดสอบใน JupyterLab ซึ่งมีประโยชน์คำสั่ง %timeit"มายากล" มันใช้มาตรฐานtimeit.timeitภายใต้ประทุน ผ่านการทดสอบสำหรับ Python 3.7.3

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