list.append()
เป็นตัวเลือกที่ชัดเจนสำหรับการเพิ่มในส่วนท้ายของรายการ นี่เป็นคำอธิบายที่เหมาะสมlist.prepend()
สำหรับการขาดหายไป สมมติว่ารายการของฉันสั้นและกังวลเรื่องประสิทธิภาพเล็กน้อยคือ
list.insert(0, x)
หรือ
list[0:0] = [x]
สำนวน?
list.append()
เป็นตัวเลือกที่ชัดเจนสำหรับการเพิ่มในส่วนท้ายของรายการ นี่เป็นคำอธิบายที่เหมาะสมlist.prepend()
สำหรับการขาดหายไป สมมติว่ารายการของฉันสั้นและกังวลเรื่องประสิทธิภาพเล็กน้อยคือ
list.insert(0, x)
หรือ
list[0:0] = [x]
สำนวน?
คำตอบ:
s.insert(0, x)
รูปแบบที่พบมากที่สุด
เมื่อใดก็ตามที่คุณเห็นมันอาจถึงเวลาที่จะต้องพิจารณาใช้collection.dequeแทนรายการ
หากคุณสามารถใช้งานได้สิ่งต่อไปนี้ค่อนข้างชัดเจน
new_list = [x] + your_list
แน่นอนว่าคุณยังไม่ได้แทรกx
เข้ามาyour_list
แต่คุณได้สร้างรายการใหม่ที่มีx
คำนำไว้แล้ว
ไวยากรณ์ของสำนวนที่เตรียมไว้สำหรับรายการหลามแบบสั้นคืออะไร
โดยปกติคุณไม่ต้องการที่จะเพิ่มรายการซ้ำใน Python ซ้ำ ๆ
ถ้ามันสั้นและคุณไม่ได้ทำมันมาก ... ก็โอเค
list.insert
list.insert
สามารถใช้วิธีนี้
list.insert(0, x)
แต่นี่ไม่มีประสิทธิภาพเพราะใน Python a list
คืออาร์เรย์ของพอยน์เตอร์และ Python จะต้องใช้ตัวชี้ทุกตัวในรายการและเลื่อนลงมาหนึ่งอันเพื่อแทรกตัวชี้ไปยังวัตถุของคุณในช่องแรกดังนั้นจริงๆแล้วมีประสิทธิภาพเท่านั้น สำหรับรายการสั้น ๆ ตามที่คุณถาม
นี่คือตัวอย่างข้อมูลจากแหล่ง CPythonที่มีการนำไปใช้ - และอย่างที่คุณเห็นเราเริ่มต้นที่ส่วนท้ายของอาร์เรย์และย้ายทุกอย่างลงทีละรายการสำหรับการแทรกทุกครั้ง:
for (i = n; --i >= where; )
items[i+1] = items[i];
ถ้าคุณต้องการคอนเทนเนอร์ / รายการที่มีประสิทธิภาพในการจัดองค์ประกอบคุณต้องการรายการที่เชื่อมโยง งูหลามมีรายการที่เชื่อมโยงเป็นทวีคูณซึ่งสามารถแทรกที่จุดเริ่มต้นและจบได้อย่างรวดเร็ว - deque
ก็เรียกว่า
deque.appendleft
A collections.deque
มีวิธีการมากมายในรายการ list.sort
เป็นข้อยกเว้นทำให้deque
แตกหักไม่ได้ทั้งหมด Liskov list
ทดแทนสำหรับ
>>> set(dir(list)) - set(dir(deque))
{'sort'}
deque
นอกจากนี้ยังมีappendleft
วิธีการ (เช่นเดียวกับpopleft
) deque
เป็นคิวสองครั้งที่สิ้นสุดและรายการทวีคูณเชื่อมโยง - ไม่ว่ายาวก็มักจะใช้เวลาเท่ากันของเวลาที่จะมีอะไรบางอย่าง preprend ในสัญกรณ์ O ขนาดใหญ่ O (1) กับเวลา O (n) สำหรับรายการ นี่คือการใช้งาน:
>>> import collections
>>> d = collections.deque('1234')
>>> d
deque(['1', '2', '3', '4'])
>>> d.appendleft('0')
>>> d
deque(['0', '1', '2', '3', '4'])
deque.extendleft
ที่เกี่ยวข้องยังเป็นextendleft
วิธีการของ deque ซึ่งซ้ำแล้วซ้ำอีกเตรียม:
>>> from collections import deque
>>> d2 = deque('def')
>>> d2.extendleft('cba')
>>> d2
deque(['a', 'b', 'c', 'd', 'e', 'f'])
โปรดทราบว่าแต่ละองค์ประกอบจะได้รับการเติมครั้งละหนึ่งรายการจึงจะกลับคำสั่งซื้อของพวกเขาได้อย่างมีประสิทธิภาพ
list
เมื่อเทียบกับdeque
ก่อนอื่นเราตั้งค่าด้วยการเพิ่มซ้ำแบบซ้ำ ๆ :
import timeit
from collections import deque
def list_insert_0():
l = []
for i in range(20):
l.insert(0, i)
def list_slice_insert():
l = []
for i in range(20):
l[:0] = [i] # semantically same as list.insert(0, i)
def list_add():
l = []
for i in range(20):
l = [i] + l # caveat: new list each time
def deque_appendleft():
d = deque()
for i in range(20):
d.appendleft(i) # semantically same as list.insert(0, i)
def deque_extendleft():
d = deque()
d.extendleft(range(20)) # semantically same as deque_appendleft above
และประสิทธิภาพ:
>>> min(timeit.repeat(list_insert_0))
2.8267281929729506
>>> min(timeit.repeat(list_slice_insert))
2.5210217320127413
>>> min(timeit.repeat(list_add))
2.0641671380144544
>>> min(timeit.repeat(deque_appendleft))
1.5863927800091915
>>> min(timeit.repeat(deque_extendleft))
0.5352169770048931
deque เร็วขึ้นมาก เมื่อรายการยาวขึ้นฉันคาดว่า deque จะทำงานได้ดีขึ้น หากคุณสามารถใช้ deque extendleft
คุณจะได้รับประสิทธิภาพที่ดีที่สุด
หากมีคนพบคำถามนี้เหมือนฉันนี่คือการทดสอบประสิทธิภาพของฉันสำหรับวิธีการที่เสนอ:
Python 2.7.8
In [1]: %timeit ([1]*1000000).insert(0, 0)
100 loops, best of 3: 4.62 ms per loop
In [2]: %timeit ([1]*1000000)[0:0] = [0]
100 loops, best of 3: 4.55 ms per loop
In [3]: %timeit [0] + [1]*1000000
100 loops, best of 3: 8.04 ms per loop
อย่างที่คุณเห็นinsert
และการแบ่งส่วนนั้นเร็วกว่าการเพิ่มอย่างชัดเจนเกือบสองเท่าและใกล้เคียงกับผลลัพธ์มาก ดังที่Raymond Hettingerตั้งข้อสังเกตว่าinsert
เป็นตัวเลือกที่ใช้กันทั่วไปมากกว่าและโดยส่วนตัวแล้วผมชอบวิธีนี้ในการเพิ่มรายชื่อ
.insert
และ[0:0] = [0]
ทำงานในสถานที่พวกเขายังคงต้องจัดสรรบัฟเฟอร์ทั้งหมดอีกครั้ง