2010-07-04 4 views
25

J'essaie de modifier des éléments dans une liste en utilisant une boucle for, mais j'obtiens une erreur (voir ci-dessous). Exemple de code:Modification des éléments de la liste dans la boucle (python)

#!/usr/bin/env python 
# *-* coding: utf8 *-* 

data = [] 
data.append("some") 
data.append("example") 
data.append("data") 
data.append("here") 

for item in data: 
    data[item] = "everything" 

Erreur:

Traceback (most recent call last): 
    File "./testy.py", line 11, in <module> 
    data[item] = "everything" 
TypeError: list indices must be integers, not str 

Est-il possible de résoudre ce problème?

Répondre

57

Essayez ceci:

for i in xrange(len(data)): 
    data[i] = "everything" 

Le problème fondamental que vous rencontrez est que lorsque vous écrivez data[i], avec data étant une liste, les i doit être un entier, un index numérique dans la liste. Mais dans la boucle

for item in data 

item est la chose réelle qui est la liste, à savoir une chaîne, et non l'indice numérique de la chose. xrange est un itérateur qui produit des nombres au lieu des valeurs de la liste, vous pouvez donc l'utiliser.

Une alternative serait

for i, _ in enumerate(data): 
    data[i] = "everything" 

La fonction enumerate vous donne un itérateur sur tuples de la forme (index, item), donc tout ce que vous devez faire est de prendre l'index et oublier l'élément. Je ne suis pas sûr que d'une façon ou l'autre (enumerate ou xrange) sera significativement plus rapide ou mieux, car je pense que les listes stockent leur longueur dans une variable de sorte qu'il peut être rapidement consulté sans compter les éléments de la liste.

Cependant, si vous avez besoin de l'ancienne valeur de la liste pour calculer la nouvelle valeur de la liste, le chemin sera probablement un peu plus rapide enumerate parce que vous éviter de faire regarder Python l'élément dans la liste:

for i, item in enumerate(data): 
    data[i] = func(item) 

Ce genre de chose est mieux exprimée en compréhension de liste, si:

data = [func(item) for item in data] 

Lorsque vous faites cela, Python passera par chaque élément data, appliquer la fonction, et construire une nouvelle liste des résultats automatiquement, y Vous n'avez pas besoin de mettre le résultat de func(item) au bon endroit dans la liste. Votre exemple original pourrait effectivement être exprimé comme suit:

+0

Il semble un peu étrange (ou solution de contournement), mais il fonctionne correctement. Je ne savais pas que les éléments primordiaux (dans la liste) devaient recevoir leur ID. Merci. –

+4

@sigo: ce n'est en fait pas une solution de contournement, c'est la façon 100% correcte et parfaitement normale de faire ce genre de tâche (mais notez ce que j'ai dit à propos des listes de compréhension). –

+2

Dans ce cas particulier, la compréhension de la liste pourrait être remplacée par la plus rapide 'data = [" tout "] * len (data)'. – EOL

5

Les éléments de la liste sont accessibles par un entier, i. e. dans votre exemple data[1] == 'example'. C'est pourquoi Python se plaint lorsque vous utilisez une chaîne comme recherche.

Si vous voulez trouver un élément dans une liste par sa valeur, vous pouvez utiliser data.index("value"):

data[data.index("some")] = "something else" 

Mais si vous voulez juste faire une boucle sur eux, utiliser enumerate() comme David a suggéré.

0

L'indexation d'une liste en utilisant des entiers pourrait être inefficace. Il est probable que python stocke les éléments de la liste en utilisant une table liée avec des pointeurs sous-jacents.Dans ce cas, pour trouver un objet spécifique, python doit traverser la liste jusqu'au i-ème élément.

Il est suggéré que l'utilisation du format comme cela pourrait être efficace: un [:] = [x * x pour x dans]

Questions connexes