Acessando o índice em loops 'for'?


3606

Como acesso o índice em um forloop como o seguinte?

ints = [8, 23, 45, 12, 78]
for i in ints:
    print('item #{} = {}'.format(???, i))

Eu quero obter esta saída:

item #1 = 8
item #2 = 23
item #3 = 45
item #4 = 12
item #5 = 78

Quando faço um forloop usando um loop, como faço para acessar o índice do loop, de 1 a 5 nesse caso?


42
Observe que os índices em python iniciam em 0, portanto, os índices para sua lista de exemplos são de 0 a 4 e não de 1 a 5
plugwash

Respostas:


6119

O uso de uma variável de estado adicional, como uma variável de índice (que você normalmente usaria em linguagens como C ou PHP), é considerada não-pitônica.

A melhor opção é usar a função interna enumerate(), disponível no Python 2 e 3:

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

Confira o PEP 279 para mais.


61
Como Aaron aponta abaixo, use start = 1 se quiser obter 1-5 em vez de 0-4.
Clozach 31/03/19

2
Não enumerateincorre em outra sobrecarga?
TheRealChx101

@ TheRealChx101 de acordo com meus testes (Python 3.6.3), a diferença é insignificante e às vezes até favorável enumerate.
Błotosmętek

804

Usando um loop for, como acesso o índice do loop, de 1 a 5 neste caso?

Use enumeratepara obter o índice com o elemento conforme você itera:

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

E observe que os índices do Python começam em zero, então você obteria 0 a 4 com o acima. Se você deseja a contagem de 1 a 5, faça o seguinte:

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

Fluxo de controle unidiomatic

O que você está pedindo é o equivalente Pythonic do seguinte, que é o algoritmo que a maioria dos programadores de linguagens de nível inferior usaria:

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

Ou em idiomas que não possuem um loop for-each:

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

ou às vezes mais comumente (mas unidiomaticamente) encontrado no Python:

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

Use a função enumerar

A enumeratefunção do Python reduz a desordem visual, ocultando a contabilidade dos índices e encapsulando o iterável em outro iterável (um enumerateobjeto) que produz uma tupla de dois itens do índice e o item que o iterável original forneceria. É assim:

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

Esse exemplo de código é razoavelmente bem o exemplo canônico da diferença entre o código idiomático do Python e o código que não é. O código linguístico é sofisticado (mas não complicado), o Python, escrito da maneira que ele deveria ser usado. O código linguístico é esperado pelos projetistas da linguagem, o que significa que geralmente esse código não é apenas mais legível, mas também mais eficiente.

Obtendo uma contagem

Mesmo que você não precise de índices à medida que avança, mas precisa de uma contagem das iterações (às vezes desejáveis) com as quais pode começar 1e o número final será sua contagem.

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

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

A contagem parece ser mais o que você pretende solicitar (em oposição ao índice) quando disse que queria de 1 a 5.


Quebrando-o - uma explicação passo a passo

Para detalhar esses exemplos, digamos que temos uma lista de itens que queremos iterar com um índice:

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

Agora passamos esse iterável para enumerar, criando um objeto enumerado:

enumerate_object = enumerate(items) # the enumerate object

Podemos extrair o primeiro item dessa iterável que entraríamos em loop com a nextfunção:

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

E vemos que obtemos uma tupla do 0primeiro índice e 'a'do primeiro item:

(0, 'a')

podemos usar o que é chamado de " descompactação de sequência " para extrair os elementos dessa duas tuplas:

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

e quando inspecionamos index, descobrimos que ele se refere ao primeiro índice, 0, e itemao primeiro item 'a',.

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

Conclusão

  • Os índices Python começam em zero
  • Para obter esses índices de uma iterável à medida que você itera, use a função enumerar
  • O uso de enumerar da maneira idiomática (junto com a descompactação da tupla) cria um código mais legível e de manutenção:

Então faça o seguinte:

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

1
O exemplo " Obtendo uma contagem " funciona quando itemsestá vazio?
Bergi 22/02

Estou enviando dados usando ajax para visualizações do Django como uma matriz na forma de dois valores em uma variável legData com valores como [1406, 1409]. Se eu imprimir no console usando print(legData), a saída será [1406,1409] . No entanto, se eu tentar analisar os valores individuais da lista como for idx, xLeg in enumerate(legData): print(idx, xLeg), obtém-me uma saída de números inteiros individuais como [, 1, 4, 0, 6 e assim por diante em relação aos índices 0, 1, 2, 3, 4 etc. (sim, os colchetes e a vírgula também estão sendo exibidos como se fossem parte dos dados ). o que há de errado aqui?
user12379095

@ user12379095 você provavelmente possui os dados do tipo errado (uma string) e precisa convertê-los em uma lista real de números, em vez de em uma string. Isso é um pouco fora do assunto aqui, exclua seu comentário e sinalize o meu para ser excluído, pois não é mais necessário quando você vê isso.
Aaron Hall

152

É muito simples iniciá-lo a partir 1de 0:

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

Nota

Dica importante, embora um pouco enganosa, pois indexserá um tuple (idx, item)aqui. Bom para ir.


11
A questão era sobre índices de lista; como eles começam de 0, não adianta começar de outro número, já que os índices estão errados (sim, o OP também disse errado na pergunta). Caso contrário, chamar a variável que é tupla index, itemapenas indexé muito enganador, como você observou. Basta usar for index, item in enumerate(ints).
Antti Haapala

1
Melhor é colocar o índice entre pares de parênteses como (index), ele funcionará nas versões 2 e 3. do Python
hygull

1
@AnttiHaapala A razão, presumo, é que a saída esperada da pergunta começa no índice 1 em vez de 0
pushkin

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

10
Provavelmente deveria ser xrangepara o pré-3.0.
2145 Ben Blank

43
Em vez disso, use enumerar
saulspatz

3
Para o Python 2.3 acima, use a função interna enumerar, pois é mais Pythonic.
213 Januarvs

Enumerar nem sempre é melhor - depende dos requisitos do aplicativo. Na minha situação atual, os relacionamentos entre os comprimentos dos objetos são significativos para minha aplicação. Embora tenha começado a usar enumerar, mudei para essa abordagem para evitar a necessidade de escrever uma lógica para selecionar qual objeto enumerar.
ADG

1
@ adg Não vejo como evitar enumeratesalva qualquer lógica; você ainda precisa selecionar com qual objeto indexar i, não?
chepner

47

Como é a norma em Python, existem várias maneiras de fazer isso. Em todos os exemplos, assuma:lst = [1, 2, 3, 4, 5]

1. Usando enumerar ( considerado mais idiomático )

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

Essa também é a opção mais segura na minha opinião, porque a chance de entrar em uma recursão infinita foi eliminada. O item e seu índice são mantidos em variáveis ​​e não há necessidade de escrever nenhum código adicional para acessar o item.

2. Criando uma variável para manter o índice ( usandofor )

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

3. Criando uma variável para manter o índice ( usandowhile )

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

4. Sempre há outra maneira

Como explicado anteriormente, existem outras maneiras de fazer isso que não foram explicadas aqui e podem até se aplicar mais em outras situações. por exemplo, usando itertools.chaincom for. Ele lida com loops aninhados melhor do que os outros exemplos.


30

Do modo antigo:

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

Compreensão da lista:

[ (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)
>>> 

3
Isso não está errado e é usado em C / C ++ e outros. É considerado não-pitonico, mas também pode ser usado em python. Como soluções simples que a decompõem na fonte: +
Valor Naram 29/07

Alguns extremistas de python diriam, não faça isso. Mas eu disse que só para indicar que há mais do que uma maneira possível
Valor Naram

21

A maneira mais rápida de acessar índices de lista dentro de loop no Python 2.7 é usar o método range para pequenas listas e enumerar o método para listas de tamanho médio e grande.

Consulte as diferentes abordagens que podem ser usadas para iterar sobre a lista e acessar o valor do índice e suas métricas de desempenho (que eu acho que seriam úteis para você) nos exemplos de código abaixo:

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

Veja métricas de desempenho para cada método abaixo:

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

Como resultado, usar range método é o mais rápido da lista, com 1000 itens. Para lista com tamanho> 10 000 itensenumerate é o vencedor.

Adicionando alguns links úteis abaixo:


5
"legibilidade conta" A diferença de velocidade na faixa pequena <1000 é insignificante. É 3% mais lento em uma métrica de tempo já pequena.

Que tal atualizar a resposta para o Python 3?
Georgy

14

Primeiro, os índices serão de 0 a 4. Os idiomas de programação começam a contar de 0; não esqueça disso ou você encontrará uma exceção fora dos limites. Tudo o que você precisa no loop for é uma variável contando de 0 a 4 da seguinte forma:

for x in range(0, 5):

Lembre-se de que eu escrevi de 0 a 5 porque o loop para um número antes do máximo. :)

Para obter o valor de um índice, use

list[index]

13

Aqui está o que você obtém ao acessar o índice em forloops:

for i in enumerate(items): print(i)

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

for i in enumerate(items):
    print("index/value", i)

Resultado:

# index/value (0, 8)
# index/value (1, 23)
# index/value (2, 45)
# index/value (3, 12)
# index/value (4, 78)

for i, val in enumerate(items): print(i, val)

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

for i, val in enumerate(items):
    print("index", i, "for value", val)

Resultado:

# index 0 for value 8
# index 1 for value 23
# index 2 for value 45
# index 3 for value 12
# index 4 for value 78

for i, val in enumerate(items): print(i)

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

for i, val in enumerate(items):
    print("index", i)

Resultado:

# index 0
# index 1
# index 2
# index 3
# index 4

12

De acordo com esta discussão: http://bytes.com/topic/python/answers/464012-objects-list-index

Iteração de contador de loop

O idioma atual para fazer um loop sobre os índices faz uso da rangefunção interna:

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

O loop sobre elementos e índices pode ser alcançado pelo idioma antigo ou usando a nova zipfunção interna:

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

ou

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

via http://www.python.org/dev/peps/pep-0212/


22
Isso não funcionará na iteração através de geradores. Basta usar enumerate ().
Tadeck 31/03

Atualmente, o idioma atual é enumerado, não a chamada de intervalo.
precisa saber é o seguinte

e é o mesmo que a resposta mais antiga: stackoverflow.com/a/522576/6451573
Jean-François Fabre

11

Você pode fazer isso com este código:

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

for value in (ints):
    index +=1
    print index, value

Use este código se precisar redefinir o valor do índice no final do loop:

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

for value in (ints):
    index +=1
    print index, value
    if index >= len(ints)-1:
        index = 0

10

A melhor solução para esse problema é usar a função enumerar python embutida.
enumerar retorno tupla
primeiro valor é índice
segundo valor é elemento da matriz nesse índice

In [1]: ints = [8, 23, 45, 12, 78]

In [2]: for idx, val in enumerate(ints):
   ...:         print(idx, val)
   ...:     
(0, 8)
(1, 23)
(2, 45)
(3, 12)
(4, 78)

9

Na sua pergunta, você escreve "como faço para acessar o índice do loop, de 1 a 5 neste caso?"

No entanto, o índice para uma lista é executado a partir de zero. Portanto, precisamos saber se o que você realmente deseja é o índice e o item para cada item em uma lista, ou se você realmente deseja números começando de 1. Felizmente, no Python, é fácil fazer um ou ambos.

Primeiro, para esclarecer, a enumeratefunção retorna iterativamente o índice e o item correspondente para cada item em uma lista.

alist = [1, 2, 3, 4, 5]

for n, a in enumerate(alist):
    print("%d %d" % (n, a))

A saída para o acima é então,

0 1
1 2
2 3
3 4
4 5

Observe que o índice é executado a partir de 0. Esse tipo de indexação é comum entre as linguagens de programação modernas, incluindo Python e C.

Se você deseja que seu loop abranja uma parte da lista, você pode usar a sintaxe padrão do Python para uma parte da lista. Por exemplo, para fazer um loop do segundo item em uma lista até o último item, mas não incluindo, você pode usar

for n, a in enumerate(alist[1:-1]):
    print("%d %d" % (n, a))

Observe que mais uma vez, o índice de saída é executado de 0,

0 2
1 3
2 4

Isso nos leva à start=nmudança para enumerate(). Isso simplesmente compensa o índice; você pode simplesmente adicionar um número ao índice dentro do loop.

for n, a in enumerate(alist, start=1):
    print("%d %d" % (n, a))

para o qual a saída é

1 1
2 2
3 3
4 4
5 5

9

Se eu fosse iterar nums = [1, 2, 3, 4, 5]eu faria

for i, num in enumerate(nums, start=1):
    print(i, num)

Ou obtenha o comprimento como l = len(nums)

for i in range(l):
    print(i+1, nums[i])

7

Se não houver valor duplicado na lista:

for i in ints:
    indx = ints.index(i)
    print(i, indx)

1
Observe que a primeira opção não deve ser usada, pois só funciona corretamente quando cada item da sequência é único.
Stam Kaly

2
A primeira opção é O (n²), uma péssima idéia. Se sua lista tiver 1000 elementos, levará literalmente 1000 vezes mais tempo que o uso enumerate. Você deve excluir esta resposta.
Boris

5

Você também pode tentar o seguinte:

data = ['itemA.ABC', 'itemB.defg', 'itemC.drug', 'itemD.ashok']
x = []
for (i, item) in enumerate(data):
      a = (i, str(item).split('.'))
      x.append(a)
for index, value in x:
     print(index, value)

A saída é

0 ['itemA', 'ABC']
1 ['itemB', 'defg']
2 ['itemC', 'drug']
3 ['itemD', 'ashok']

3

Você pode usar o indexmétodo

ints = [8, 23, 45, 12, 78]
inds = [ints.index(i) for i in ints]

Edição Destacado no comentário que este método não funciona se houver duplicatas ints, o método abaixo deve funcionar para quaisquer valores em ints:

ints = [8, 8, 8, 23, 45, 12, 78]
inds = [tup[0] for tup in enumerate(ints)]

Ou alternativamente

ints = [8, 8, 8, 23, 45, 12, 78]
inds = [tup for tup in enumerate(ints)]

se você deseja obter o índice e o valor em ints como uma lista de tuplas.

Ele usa o método de enumeratena resposta selecionada para esta pergunta, mas com compreensão de lista, tornando-o mais rápido com menos código.


2

Resposta simples usando o Loop While:

arr = [8, 23, 45, 12, 78]
i = 0
while i<len(arr):
    print("Item ",i+1," = ",arr[i])
    i +=1

Resultado:

insira a descrição da imagem aqui


1

Para imprimir tupla de (índice, valor) na compreensão da lista usando um forloop:

ints = [8, 23, 45, 12, 78]
print [(i,ints[i]) for i in range(len(ints))]

Resultado:

[(0, 8), (1, 23), (2, 45), (3, 12), (4, 78)]

1

Isso serve bem a esse propósito:

list1 = [10, 'sumit', 43.21, 'kumar', '43', 'test', 3]
for x in list1:
    print('index:', list1.index(x), 'value:', x)

4
Isso será interrompido se houver elementos repetidos na lista, assim como index()a primeira ocorrência será pesquisada x, sem mencionar o tempo O ( n ^ 2 ) necessário para pesquisar cada elemento.
Peter Szoldan

totalmente de acordo que não funcionará para elementos duplicados na lista. Afinal, eu também estou aprendendo python.
Sumit Kumar
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.