Python sử dụng liệt kê bên trong danh sách hiểu


125

Giả sử tôi có một danh sách như thế này:

mylist = ["a","b","c","d"]

Để có được các giá trị được in cùng với chỉ mục của chúng, tôi có thể sử dụng enumeratehàm Python như thế này

>>> for i,j in enumerate(mylist):
...     print i,j
...
0 a
1 b
2 c
3 d
>>>

Bây giờ, khi tôi cố gắng sử dụng nó bên trong, list comprehensionnó sẽ báo lỗi

>>> [i,j for i,j in enumerate(mylist)]
  File "<stdin>", line 1
    [i,j for i,j in enumerate(mylist)]
           ^
SyntaxError: invalid syntax

Vì vậy, câu hỏi của tôi là: cách sử dụng liệt kê chính xác trong danh sách hiểu là gì?

Câu trả lời:


166

Thử cái này:

[(i, j) for i, j in enumerate(mylist)]

Bạn cần phải đặt i,jtrong một tuple để hiểu danh sách để làm việc. Ngoài ra, do enumerate() đã trả về một tuple, bạn có thể trả lại trực tiếp mà không cần giải nén nó trước:

[pair for pair in enumerate(mylist)]

Dù bằng cách nào, kết quả được trả về là như mong đợi:

> [(0, 'a'), (1, 'b'), (2, 'c'), (3, 'd')]

4
Không bắt buộc phải là một tuple. Bất kỳ biểu thức nào sử dụng i và j trả về giá trị sẽ thực hiện
Alvaro

sử dụng phép liệt kê là tuyệt vời, làm thế nào để làm cho nó hiệu quả hơn bằng cách sử dụng itertools
Pramit

3
Chỉ cần nhớ rằng một tuple được xây dựng bởi , không những (). Vì vậy, "đặt i,jbên trong một tuple" không có ý nghĩa gì, vì i,jđã là một tuple! Vấn đề là trình phân tích cú pháp danh sách cần parens cho nhóm câu lệnh.
cowbert

46

Chỉ cần thực sự rõ ràng, điều này không có gì để làm với enumerate và tất cả mọi thứ để làm với cú pháp hiểu danh sách.

Danh sách hiểu này trả về một danh sách các bộ dữ liệu:

[(i,j) for i in range(3) for j in 'abc']

đây là danh sách các bài viết:

[{i:j} for i in range(3) for j in 'abc']

một danh sách các danh sách:

[[i,j] for i in range(3) for j in 'abc']

một lỗi cú pháp:

[i,j for i in range(3) for j in 'abc']

Không phù hợp (IMHO) và khó hiểu với cú pháp hiểu từ điển:

>>> {i:j for i,j in enumerate('abcdef')}
{0: 'a', 1: 'b', 2: 'c', 3: 'd', 4: 'e', 5: 'f'}

Và một bộ tuples:

>>> {(i,j) for i,j in enumerate('abcdef')}
set([(0, 'a'), (4, 'e'), (1, 'b'), (2, 'c'), (5, 'f'), (3, 'd')])

Như Óscar López đã nêu, bạn có thể chuyển trực tiếp bộ dữ liệu liệt kê:

>>> [t for t in enumerate('abcdef') ] 
[(0, 'a'), (1, 'b'), (2, 'c'), (3, 'd'), (4, 'e'), (5, 'f')]

32

Hoặc, nếu bạn không khăng khăng sử dụng cách hiểu danh sách:

>>> mylist = ["a","b","c","d"]
>>> list(enumerate(mylist))
[(0, 'a'), (1, 'b'), (2, 'c'), (3, 'd')]

12

Nếu bạn đang sử dụng danh sách dài, nó sẽ xuất hiện danh sách hiểu nhanh hơn, chưa kể dễ đọc hơn.

~$ python -mtimeit -s"mylist = ['a','b','c','d']" "list(enumerate(mylist))"
1000000 loops, best of 3: 1.61 usec per loop
~$ python -mtimeit -s"mylist = ['a','b','c','d']" "[(i, j) for i, j in enumerate(mylist)]"
1000000 loops, best of 3: 0.978 usec per loop
~$ python -mtimeit -s"mylist = ['a','b','c','d']" "[t for t in enumerate(mylist)]"
1000000 loops, best of 3: 0.767 usec per loop

2
+1 Tôi đã không kiểm tra nó, nhưng tôi sẽ đặt cược [t for t in enumerate(my list)]thậm chí còn nhanh hơn.
con sói

11

Đây là một cách để làm điều đó:

>>> mylist = ['a', 'b', 'c', 'd']
>>> [item for item in enumerate(mylist)]
[(0, 'a'), (1, 'b'), (2, 'c'), (3, 'd')]

Ngoài ra, bạn có thể làm:

>>> [(i, j) for i, j in enumerate(mylist)]
[(0, 'a'), (1, 'b'), (2, 'c'), (3, 'd')]

Lý do bạn gặp lỗi là do bạn đã bỏ lỡ () xung quanh ijđể biến nó thành một tuple.



0

Tất cả các chàng trai trả lời tuyệt vời. Tôi biết câu hỏi ở đây là cụ thể để liệt kê nhưng làm thế nào về một cái gì đó như thế này, chỉ là một quan điểm khác

from itertools import izip, count
a = ["5", "6", "1", "2"]
tupleList = list( izip( count(), a ) )
print(tupleList)

Nó trở nên mạnh mẽ hơn, nếu người ta phải lặp lại nhiều danh sách song song về mặt hiệu suất. Chỉ là một ý nghĩ

a = ["5", "6", "1", "2"]
b = ["a", "b", "c", "d"]
tupleList = list( izip( count(), a, b ) )
print(tupleList)
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.