Trong Python, làm cách nào để lập chỉ mục một danh sách với một danh sách khác?


130

Tôi muốn lập chỉ mục một danh sách với một danh sách khác như thế này

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

và T cuối cùng sẽ là một danh sách chứa ['a', 'd', 'h'].

Có cách nào tốt hơn

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

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

Câu trả lời:


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

6
Đây có phải là nhanh hơn một vòng lặp for hoặc chỉ ngắn hơn?
Daniel Andrén

9
@daniel: cả hai + được đề xuất
SilentGhost

13
Một bài kiểm tra thời gian nhanh (không có pysco hay bất cứ thứ gì, vì vậy hãy làm cho nó đúng như bạn muốn) cho thấy mức độ hiểu danh sách nhanh hơn 2,5 lần so với vòng lặp (1000 phần tử, lặp lại 10000 lần).
James Hopkin

2
(sử dụng bản đồ và lambda thậm chí còn chậm hơn - được mong đợi, vì nó gọi một hàm cho mỗi lần lặp)
James Hopkin

+1 Nếu danh sách lập chỉ mục là tùy ý, thì cách liệt kê danh sách là cách. Tôi nghĩ mặc dù vậy, khi có thể, dường như không phải là trường hợp ở đây, lát thậm chí còn nhanh hơn.
Jaime

40

Nếu bạn đang sử dụng numpy, bạn có thể thực hiện cắt lát mở rộng như thế:

>>> 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')

... và có lẽ nhanh hơn nhiều (nếu hiệu suất đủ để lo lắng với việc nhập khẩu khó chịu)


5
Thử nghiệm thời gian nhanh của tôi cho thấy rằng sử dụng np.array thực sự chậm hơn gần 3 lần (bao gồm cả chuyển đổi thành mảng).
Andrzej Pronobis

Nó hoạt động tốt hơn nếu bạn cần chuyển đổi nó cho dù sao hoạt động mảng. Quá tốn thời gian cho các hoạt động danh sách thường xuyên.
frankliuao

9

Một cách tiếp cận chức năng:

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

from operator import itemgetter

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

Điều này sẽ không hoạt động nếu bchỉ chứa một mục.
blhsing


5

Tôi không hài lòng với bất kỳ cách tiếp cận nào trong số này, vì vậy tôi đã đưa ra một Flexlistlớp cho phép lập chỉ mục linh hoạt, theo số nguyên, lát hoặc danh sách chỉ mục:

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

Mà, ví dụ của bạn, bạn sẽ sử dụng như:

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

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

cũng thể hiện sức mạnh và tính linh hoạt của Python!
đám đông

Thật dễ dàng để mở rộng điều này cũng như cho mã hiện có. Chỉ cần gọi existing_list = Flexlist(existing_list)và chúng tôi có chức năng cần thiết mà không vi phạm bất kỳ mã nào
Yesh

1
L= {'a':'a','d':'d', 'h':'h'}
index= ['a','d','h'] 
for keys in index:
    print(L[keys])

Tôi sẽ sử dụng một Dict addmong muốn keysđểindex


0

Bạn cũng có thể sử dụng __getitem__phương thức kết hợp mapnhư sau:

L = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h']
Idx = [0, 3, 7]
res = list(map(L.__getitem__, Idx))
print(res)
# ['a', 'd', 'h']
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.