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?

Joan Venge
fonte
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.

Mike Hordecki
fonte
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)
Aaron Hall
fonte
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.

AJ
fonte
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]
David Hanak
fonte
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.

Charitoo
fonte
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)
>>> 
Charlie Martin
fonte
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:

Andriy Ivaneyko
fonte
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]
ytpillai
fonte
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
Andy
fonte
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/

thinker007
fonte
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
Liam
fonte
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)
Anurag Misra
fonte
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
DrM
fonte
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])
Ankur Kothari
fonte
7

Se não houver valor duplicado na lista:

for i in ints:
    indx = ints.index(i)
    print(i, indx)
RIshu
fonte
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']
Ashok Kumar Jayaraman
fonte
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.

PyRsquared
fonte
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

Amar Kumar
fonte
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)]
lola
fonte
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)
Sumit Kumar
fonte
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