Câu hỏi Truy cập chỉ mục trong các vòng 'cho'?


Làm cách nào để truy cập vào chỉ mục cho danh sách như sau?

ints = [8, 23, 45, 12, 78]

Khi tôi lặp qua nó bằng for vòng lặp, làm cách nào để truy cập vào chỉ mục vòng lặp, từ 1 đến 5 trong trường hợp này?


2563
2018-02-06 22:47


gốc




Các câu trả lời:


Sử dụng một biến trạng thái bổ sung, chẳng hạn như một biến chỉ mục (mà bạn thường sử dụng trong các ngôn ngữ như C hoặc PHP), được coi là không phải là pythonic.

Tùy chọn tốt hơn là sử dụng chức năng tích hợp sẵn enumerate(), có sẵn trong cả Python 2 và 3:

for idx, val in enumerate(ints):
    print(idx, val)

Kiểm tra PEP 279 để biết thêm.


4456
2018-02-06 22:52



Như Aaron chỉ ra dưới đây, sử dụng start = 1 nếu bạn muốn nhận 1-5 thay vì 0-4. - clozach


Sử dụng vòng lặp for, làm cách nào để truy cập vào chỉ mục vòng lặp, từ 1 đến 5 trong trường hợp này?

Sử dụng enumerate để lấy chỉ mục với phần tử khi bạn lặp:

for index, item in enumerate(items):
    print(index, item)

Và lưu ý rằng các chỉ mục của Python bắt đầu ở mức 0, vì vậy bạn sẽ nhận được từ 0 đến 4 với phần trên. Nếu bạn muốn đếm, 1 đến 5, hãy làm điều này:

for count, item in enumerate(items, start=1):
    print(count, item)

Dòng điều khiển không đơn điệu

Những gì bạn đang yêu cầu là tương đương với Pythonic sau đây, đó là thuật toán mà hầu hết các lập trình viên của các ngôn ngữ cấp thấp sẽ sử dụng:

index = 0            # Python's indexing starts at zero
for item in items:   # Python's for loops are a "for each" loop 
    print(index, item)
    index += 1

Hoặc bằng các ngôn ngữ không có vòng lặp cho mỗi:

index = 0
while index < len(items):
    print(index, items[index])
    index += 1

hoặc đôi khi phổ biến hơn (nhưng không tự nhiên) được tìm thấy trong Python:

for index in range(len(items)):
    print(index, items[index])

Sử dụng hàm liệt kê

Python enumerate chức năng làm giảm sự lộn xộn thị giác bằng cách ẩn các kế toán cho các chỉ mục, và đóng gói các iterable thành một iterable (một enumerate đối tượng) tạo ra một tuple hai mục của chỉ mục và mục mà bản gốc có thể lặp lại sẽ cung cấp. Điều đó trông như thế này:

for index, item in enumerate(items, start=0):   # default is zero
    print(index, item)

Mẫu mã này khá tốt kinh điển ví dụ về sự khác biệt giữa mã là thành ngữ của Python và mã không phải là. Mã thành ngữ là Python phức tạp (nhưng không phức tạp), được viết theo cách mà nó được dự định sẽ được sử dụng. Mã thành ngữ được mong đợi bởi các nhà thiết kế ngôn ngữ, điều này có nghĩa là mã này thường không chỉ dễ đọc hơn mà còn hiệu quả hơn.

Nhận số lượng

Ngay cả khi bạn không cần chỉ mục khi bạn đi, nhưng bạn cần đếm số lần lặp lại (đôi khi mong muốn), bạn có thể bắt đầu bằng 1 và số cuối cùng sẽ là số của bạn.

for count, item in enumerate(items, start=1):   # default is zero
    print(item)

print('there were {0} items printed'.format(count))

Số lượng có vẻ là nhiều hơn những gì bạn có ý định yêu cầu (như trái ngược với chỉ mục) khi bạn nói rằng bạn muốn từ 1 đến 5.


Phá vỡ nó - một giải thích từng bước

Để chia nhỏ các ví dụ này, chúng ta có một danh sách các mục mà chúng ta muốn lặp lại với một chỉ mục:

items = ['a', 'b', 'c', 'd', 'e']

Bây giờ chúng ta chuyển qua lần lặp này để liệt kê, tạo một đối tượng liệt kê:

enumerate_object = enumerate(items) # the enumerate object

Chúng ta có thể kéo mục đầu tiên ra khỏi vòng lặp này mà chúng ta sẽ nhận được trong một vòng lặp với next chức năng:

iteration = next(enumerate_object) # first iteration from enumerate
print(iteration)

Và chúng ta thấy chúng ta có được một bộ 0, chỉ mục đầu tiên và 'a', mục đầu tiên:

(0, 'a')

chúng ta có thể sử dụng cái được gọi là "giải nén chuỗi"để trích xuất các phần tử từ hai bộ này:

index, item = iteration
#   0,  'a' = (0, 'a') # essentially this.

và khi chúng tôi kiểm tra index, chúng tôi thấy nó là chỉ số đầu tiên, 0 và item đề cập đến mục đầu tiên, 'a'.

>>> print(index)
0
>>> print(item)
a

Phần kết luận

  • Chỉ số Python bắt đầu ở mức 0
  • Để có được các chỉ mục này từ một iterable khi bạn lặp qua nó, hãy sử dụng hàm liệt kê
  • Sử dụng liệt kê theo cách thành ngữ (cùng với giải nén tuple) tạo mã dễ đọc hơn và có thể bảo trì được:

Vì vậy, làm điều này:

for index, item in enumerate(items, start=0):   # Python indexes start at zero
    print(index, item)

519
2018-01-21 17:11





Nó khá đơn giản để bắt đầu nó từ 1 khác hơn 0:

for index, item in enumerate(iterable, start=1):
   print index, item

chú thích

Gợi ý quan trọng, mặc dù một chút gây hiểu lầm kể từ index sẽ là một tuple  (idx, item) đây. Tốt để đi.


105
2018-05-27 10:04



Câu hỏi là về các chỉ mục danh sách; kể từ khi họ bắt đầu từ 0 có rất ít điểm bắt đầu từ số khác vì các chỉ số sẽ sai (có, OP cũng nói sai trong câu hỏi). Nếu không, hãy gọi biến đó là bộ index, item chỉ index là rất sai lầm, như bạn đã lưu ý. Chỉ dùng for index, item in enumerate(ints). - Antti Haapala
Tốt hơn là để kèm theo chỉ mục bên trong cặp dấu ngoặc đơn là (chỉ mục), nó sẽ hoạt động trên cả hai phiên bản Python 2 và 3. - hygull


for i in range(len(ints)):
   print i, ints[i]

67
2018-02-06 22:49



Điều đó có lẽ nên là xrange cho trước 3.0. - Ben Blank
Không, trừ khi tốc độ là cần thiết người ta không nên tối ưu hóa. - Georg Schölly
Người ta không nên sớm tối ưu hóa, mặc dù tôi đồng ý trong trường hợp này, do có cùng mã hoạt động trong 2.x và 3.x.
Sử dụng liệt kê thay thế - saulspatz
Đối với Python 2.3 ở trên, hãy sử dụng hàm dựng sẵn liệt kê vì nó có nhiều Pythonic hơn. - januarvs


Như là tiêu chuẩn trong Python có một số cách để làm điều này. Trong tất cả các ví dụ giả định: lst = [1, 2, 3, 4, 5]

1. Sử dụng liệt kê (được coi là thành ngữ nhất)

for index, element in enumerate(lst):
    # do the things that need doing here

Đây cũng là lựa chọn an toàn nhất trong quan điểm của tôi vì cơ hội đi vào đệ quy vô hạn đã bị loại bỏ. Cả mục và chỉ mục của nó đều được giữ trong các biến và không cần viết thêm mã nào nữa để truy cập mục.

2. Tạo một biến để giữ chỉ mục (sử dụng for)

for index in range(len(lst)):   # or xrange
    # you will have to write extra code to get the element

3. Tạo một biến để giữ chỉ mục (sử dụng while)

index = 0
while index < len(lst):
    # you will have to write extra code to get the element
    index += 1  # escape infinite recursion

4. Luôn luôn có một cách khác

Như đã giải thích trước đây, có nhiều cách khác để làm điều này mà chưa được giải thích ở đây và thậm chí họ có thể áp dụng nhiều hơn trong các tình huống khác. ví dụ sử dụng itertools.chain với cho. Nó xử lý vòng lặp lồng nhau tốt hơn so với các ví dụ khác.


34
2017-08-15 02:17



Ở điểm 2, truy cập bằng .index() có độ phức tạp tuyến tính, có nghĩa là độ phức tạp của vòng lặp của bạn bây giờ là bậc hai. Hơn nữa, nó không hoạt động khi danh sách của bạn chứa nhiều phần tử bằng nhau, vì nó luôn trả về chỉ mục của phần tử đầu tiên. - Aristide
@Charitoo Tôi đang xóa điểm 2 vì nó thực sự không bao giờ nên được sử dụng - jamylak
bạn có thể có nhiều liệt kê cùng một lúc không? Nói rằng tôi muốn tôi và J là những chỉ mục như vậy mà J> I, v.v ...? Tôi cho rằng 3 sẽ tốt hơn cho điều đó - arviman


Cách cũ thời:

for ix in range(len(ints)):
    print ints[ix]

Danh sách hiểu:

[ (ix, ints[ix]) for ix in range(len(ints))]

>>> ints
[1, 2, 3, 4, 5]
>>> for ix in range(len(ints)): print ints[ix]
... 
1
2
3
4
5
>>> [ (ix, ints[ix]) for ix in range(len(ints))]
[(0, 1), (1, 2), (2, 3), (3, 4), (4, 5)]
>>> lc = [ (ix, ints[ix]) for ix in range(len(ints))]
>>> for tup in lc:
...     print tup
... 
(0, 1)
(1, 2)
(2, 3)
(3, 4)
(4, 5)
>>> 

20
2018-02-06 22:52



Đây là không phải sai và được sử dụng trong C / C ++ và những người khác. Nó được coi là non-pythonic, nhưng cũng có thể được sử dụng trong python. Giống như các giải pháp đơn giản để chia nhỏ nguồn: + - Valor Naram
Nó nói nó sai ở đâu? - Charlie Martin
Một số trăn cực đoan sẽ nói, đừng làm thế. Nhưng tôi đã nói nó chỉ để chỉ ra rằng có nhiều cách có thể - Valor Naram


Cách nhanh nhất để truy cập các chỉ mục của danh sách trong vòng lặp trong Python 2,7 là sử dụng phương pháp phạm vi cho các danh sách nhỏ và phương pháp liệt kê cho danh sách kích thước trung bình và lớn.

Xin vui lòng xem phương pháp tiếp cận khác nhau có thể được sử dụng để lặp qua danh sách và truy cập giá trị chỉ mục và chỉ số hiệu suất của chúng (mà tôi cho rằng sẽ hữu ích cho bạn) trong các mẫu mã dưới đây:

from timeit import timeit

# Using range
def range_loop(iterable):
    for i in range(len(iterable)):
        1 + iterable[i]

# Using xrange
def xrange_loop(iterable):
    for i in xrange(len(iterable)):
        1 + iterable[i]

# Using enumerate
def enumerate_loop(iterable):
    for i, val in enumerate(iterable):
        1 + val

# Manual indexing
def manual_indexing_loop(iterable):
    index = 0
    for item in iterable:
        1 + item
        index += 1

Xem chỉ số hiệu suất cho từng phương pháp bên dưới:

from timeit import timeit

def measure(l, number=10000):
print "Measure speed for list with %d items" % len(l)
print "xrange: ", timeit(lambda :xrange_loop(l), number=number)
print "range: ", timeit(lambda :range_loop(l), number=number)
print "enumerate: ", timeit(lambda :enumerate_loop(l), number=number)
print "manual_indexing: ", timeit(lambda :manual_indexing_loop(l), number=number)

measure(range(1000))
# Measure speed for list with 1000 items
# xrange:  0.758321046829
# range:  0.701184988022
# enumerate:  0.724966049194
# manual_indexing:  0.894635915756

measure(range(10000))
# Measure speed for list with 100000 items
# xrange:  81.4756360054
# range:  75.0172479153
# enumerate:  74.687623024
# manual_indexing:  91.6308541298

measure(range(10000000), number=100)
# Measure speed for list with 10000000 items
# xrange:  82.267786026
# range:  84.0493988991
# enumerate:  78.0344707966
# manual_indexing:  95.0491430759

Kết quả là, sử dụng range là phương pháp nhanh nhất trong danh sách với 1000 mục. Đối với danh sách có kích thước> 10 000 mục enumerate là người chiến thắng.

Thêm một số liên kết hữu ích dưới đây:


16
2017-08-04 09:49



"khả năng đọc đếm" Sự khác biệt về tốc độ trong phạm vi <1000 nhỏ là không đáng kể. Nó chậm hơn 3% trên một chỉ số thời gian đã nhỏ. - Surest Texas


Tôi không biết nếu sau đây là pythonic hay không, nhưng nó sử dụng chức năng Python enumerate và in chỉ mục và giá trị.

int_list = [8, 23, 45, 12, 78]
for index, value in enumerate(int_list):
   print(index, value)

Đầu ra:

0 8
1 23
2 45
3 12
4 78

16
2017-10-28 18:17





ints = [9, 23, 45, 12, 78]
ints.extend([1,2,3,4,5,6,7,8])
for idx, val in enumerate(ints):
    print(idx,val)

Bằng cách này bạn có thể mở rộng danh sách. Mở rộng có nghĩa là bạn có thể thêm nhiều giá trị cùng một lúc.

Để thêm vào danh sách này, bạn phải viết mã được đưa ra dưới đây:

ints = [9, 23, 45, 12, 78]
ints.append([1])
for idx, val in enumerate(ints):
    print(idx,val)

Bằng cách này, bạn có thể thêm một giá trị duy nhất tại một thời điểm. Nếu bạn viết ints.append([1]) do đó, điều này sẽ tạo danh sách phụ cho phần tử này.


15
2018-02-05 17:28





Đầu tiên, các chỉ mục sẽ từ 0 đến 4. Các ngôn ngữ lập trình bắt đầu đếm từ 0; đừng quên điều đó hoặc bạn sẽ đi qua một chỉ mục ngoài giới hạn ngoại lệ. Tất cả những gì bạn cần trong vòng lặp for là một biến đếm từ 0 đến 4 như sau:

for x in range(0, 5):

Hãy nhớ rằng tôi đã viết 0 đến 5 vì vòng lặp dừng một số trước số tối đa. :)

Để có được giá trị của việc sử dụng chỉ mục

list[index]

11
2018-05-25 15:08





Theo thảo luận này: http://bytes.com/topic/python/answers/464012-objects-list-index

Lặp lại truy cập vòng lặp

Thành ngữ hiện tại để lặp qua các chỉ mục sử dụng chức năng 'phạm vi' được tích hợp sẵn:

for i in range(len(sequence)):
    # work with index i

Việc lặp qua cả hai phần tử và chỉ số có thể đạt được bằng thành ngữ cũ hoặc bằng cách sử dụng chức năng tích hợp 'zip' mới [2]:

for i in range(len(sequence)):
    e = sequence[i]
    # work with index i and element e

hoặc là

for i, e in zip(range(len(sequence)), sequence):
    # work with index i and element e

thông qua http://www.python.org/dev/peps/pep-0212/


9
2018-05-05 07:10



Điều này sẽ không hoạt động cho việc lặp qua các trình tạo. Chỉ cần sử dụng liệt kê (). - Tadeck
Ngày nay, thành ngữ hiện tại được liệt kê, không phải là cuộc gọi phạm vi. - TankorSmash