ใน Python ฉันจะทำดัชนีรายการกับรายการอื่นได้อย่างไร


132

ฉันต้องการจัดทำดัชนีรายการกับรายการอื่นเช่นนี้

L = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h']
Idx = [0, 3, 7]
T = L[ Idx ]

และ T ควรจะเป็นรายการที่มี ['a', 'd', 'h']

มีวิธีที่ดีกว่า

T = []
for i in Idx:
    T.append(L[i])

print T
# Gives result ['a', 'd', 'h']

คำตอบ:


243
T = [L[i] for i in Idx]

7
เร็วกว่า for-loop หรือสั้นกว่าเท่านั้น?
Daniel Andrén

10
@daniel: both + recommended
SilentGhost

14
การทดสอบเวลาอย่างรวดเร็ว (ไม่มี pysco หรืออะไรก็ตามดังนั้นจงทำตามสิ่งที่คุณต้องการ) แสดงให้เห็นความเข้าใจรายการเร็วกว่าลูป 2.5 เท่า (1,000 องค์ประกอบซ้ำ 10,000 ครั้ง)
James Hopkin

2
(การใช้แผนที่และแลมบ์ดาจะช้ากว่า - เป็นที่คาดหวังเนื่องจากมันเรียกใช้ฟังก์ชันสำหรับการวนซ้ำแต่ละครั้ง)
James Hopkin

+1 หากรายการการจัดทำดัชนีเป็นไปโดยพลการคำสั่งซื้อของรายการก็เป็นหนทาง ฉันคิดว่าถ้าเป็นไปได้ซึ่งดูเหมือนจะไม่เป็นเช่นนั้นที่นี่สไลซ์จะเร็วขึ้น
Jaime

41

หากคุณกำลังใช้ numpy คุณสามารถทำการแบ่งส่วนขยายได้ดังนี้:

>>> import numpy
>>> a=numpy.array(['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h'])
>>> Idx = [0, 3, 7]
>>> a[Idx]
array(['a', 'd', 'h'], 
      dtype='|S1')

... และอาจเร็วกว่ามาก (หากประสิทธิภาพเพียงพอสำหรับข้อกังวลที่จะรบกวนการนำเข้าจำนวนมาก)


5
การทดสอบเวลาอย่างรวดเร็วของฉันแสดงให้เห็นว่าการใช้ np.array นั้นช้ากว่าเกือบ 3 เท่า (รวมถึงการแปลงเป็นอาร์เรย์)
Andrzej Pronobis

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

9

แนวทางการทำงาน:

a = [1,"A", 34, -123, "Hello", 12]
b = [0, 2, 5]

from operator import itemgetter

print(list(itemgetter(*b)(a)))
[1, 34, 12]

สิ่งนี้จะไม่ได้ผลหากbมีเพียงรายการเดียว
blhsing


5

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

class Flexlist(list):
    def __getitem__(self, keys):
        if isinstance(keys, (int, slice)): return list.__getitem__(self, keys)
        return [self[k] for k in keys]

ซึ่งในตัวอย่างของคุณคุณจะใช้เป็น:

L = Flexlist(['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h'])
Idx = [0, 3, 7]
T = L[ Idx ]

print(T)  # ['a', 'd', 'h']

ซึ่งแสดงให้เห็นถึงพลังและความยืดหยุ่นของ Python!
crowie

มันง่ายมากที่จะขยายสิ่งนี้เช่นกันสำหรับโค้ดที่มีอยู่ เพียงโทรexisting_list = Flexlist(existing_list)และเรามีการทำงานที่จำเป็นโดยไม่ทำลายรหัสใด ๆ
Yesh


0

คุณยังสามารถใช้__getitem__วิธีการนี้รวมกับmapสิ่งต่อไปนี้:

L = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h']
Idx = [0, 3, 7]
res = list(map(L.__getitem__, Idx))
print(res)
# ['a', 'd', 'h']
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.