web-dev-qa-db-fra.com

Comment remplacer des valeurs à des index spécifiques d'une liste python?

Si j'ai une liste:

to_modify = [5,4,3,2,1,0]

Et puis déclarez deux autres listes:

indexes = [0,1,3,5]
replacements = [0,0,0,0]

Comment puis-je prendre les éléments de to_modify Comme index vers indexes, puis définir les éléments correspondants dans to_modify Sur replacements, c'est-à-dire après avoir exécuté, indexes devrait être [0,0,3,0,1,0].

Apparemment, je peux le faire via une boucle for:

for ind in to_modify:
    indexes[to_modify[ind]] = replacements[ind]

Mais existe-t-il une autre façon de procéder? Puis-je utiliser operator.itemgetter D'une manière ou d'une autre?

21
Alcott

Le plus gros problème avec votre code est qu'il est illisible. Python code règle numéro un, s'il n'est pas lisible, personne ne le regardera assez longtemps pour en obtenir des informations utiles. Utilisez toujours des noms de variables descriptives. Presque bug dans votre code, revoyons-le avec de bons noms, style de relecture au ralenti:

to_modify = [5,4,3,2,1,0]
indexes = [0,1,3,5]
replacements = [0,0,0,0]

for index in indexes:
    to_modify[indexes[index]] = replacements[index]
    # to_modify[indexes[index]]
    # indexes[index]
    # Yo dawg, I heard you liked indexes, so I put an index inside your indexes
    # so you can go out of bounds while you go out of bounds.

Comme cela est évident lorsque vous utilisez des noms de variables descriptives, vous indexez la liste des index avec des valeurs en soi, ce qui n'a pas de sens dans ce cas.

De plus, lors de l'itération de 2 listes en parallèle, j'aime utiliser la fonction Zip (ou izip si vous êtes préoccupé par la consommation de mémoire, mais je ne fais pas partie de ces puristes de l'itération). Essayez donc ceci à la place.

for (index, replacement) in Zip(indexes, replacements):
    to_modify[index] = replacement

Si votre problème ne fonctionne qu'avec des listes de numéros, je dirais que @steabert a la réponse que vous cherchiez avec ce truc numpy. Cependant, vous ne pouvez pas utiliser des séquences ou d'autres types de données de taille variable comme éléments de tableaux numpy, donc si votre variable to_modify contient quelque chose comme ça, vous feriez probablement mieux de le faire avec une boucle for.

30
machine yearning

numpy a des tableaux qui vous permettent d'utiliser d'autres listes/tableaux comme indices:

import numpy
S=numpy.array(s)
S[a]=m
18
steabert

Pourquoi pas seulement:

map(s.__setitem__, a, m)
6
eph

Un peu plus lent, mais lisible je pense:

>>> s, l, m
([5, 4, 3, 2, 1, 0], [0, 1, 3, 5], [0, 0, 0, 0])
>>> d = dict(Zip(l, m))
>>> d  #dict is better then using two list i think
{0: 0, 1: 0, 3: 0, 5: 0}
>>> [d.get(i, j) for i, j in enumerate(s)]
[0, 0, 3, 0, 1, 0]
2
utdemir

pour l'index dans un:

Cela entraînera index à prendre les valeurs des éléments de a, donc les utiliser comme indices n'est pas ce que vous voulez. En Python, nous itérons sur un conteneur en effectuant une itération sur celui-ci.

"Mais attendez", vous dites: "Pour chacun de ces éléments de a, je dois travailler avec l'élément correspondant de m. Comment suis-je censé faire cela sans index?"

Facile. Nous transformons a et m en une liste de paires (élément de a, élément de m), et itérons sur les paires. Ce qui est facile à faire - utilisez simplement la fonction de bibliothèque intégrée Zip, comme suit:

for a_element, m_element in Zip(a, m):
  s[a_element] = m_element

Pour que cela fonctionne comme vous essayez de le faire, vous devez obtenir une liste d'indices sur lesquels itérer. C'est faisable: on peut utiliser range(len(a)) par exemple. Mais ne fais pas ça! Ce n'est pas ainsi que nous faisons les choses en Python. En fait, itérer directement sur ce que vous voulez répéter est une belle idée libératrice d'esprit.

qu'en est-il de operator.itemgetter

Pas vraiment pertinent ici. Le but de operator.itemgetter Est de transformer l'acte d'indexation en quelque chose, en une chose semblable à une fonction (ce que nous appelons "un appelable"), afin qu'il puisse être utilisé comme un rappel (par exemple, un ' pour le tri ou les opérations min/max). Si nous l'utilisions ici, nous devions le rappeler à chaque fois dans la boucle pour créer un nouvel itemgetter, juste pour que nous puissions l'utiliser immédiatement une fois et le jeter. Dans le contexte, c'est juste un travail occupé.

1
Karl Knechtel

Vous pouvez utiliser operator.setitem.

from operator import setitem
a = [5, 4, 3, 2, 1, 0]
ell = [0, 1, 3, 5]
m = [0, 0, 0, 0]
for b, c in Zip(ell, m):
    setitem(a, b, c)
>>> a
[0, 0, 3, 0, 1, 0]

Est-elle plus lisible ou efficace que votre solution? Je ne suis pas sûr!

0
Praveen Gollakota

Vous pouvez le résoudre en utilisant le dictionnaire

to_modify = [5,4,3,2,1,0]
indexes = [0,1,3,5]
replacements = [0,0,0,0]

dic = {}
for i in range(len(indexes)):
    dic[indexes[i]]=replacements[i]
print(dic)

for index, item in enumerate(to_modify):
    for i in indexes:
        to_modify[i]=dic[i]
print(to_modify)

La sortie sera

{0: 0, 1: 0, 3: 0, 5: 0}
[0, 0, 3, 0, 1, 0]
0