web-dev-qa-db-fra.com

Remplacer les valeurs dans la liste en utilisant Python

J'ai une liste où je veux remplacer les valeurs par None où condition () renvoie True.

[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]

Par exemple, si les contrôles de condition bool (item% 2) doit renvoyer:

[None, 1, None, 3, None, 5, None, 7, None, 9, None]

Quel est le moyen le plus efficace de le faire?

108
ak.

Construire une nouvelle liste avec une compréhension de la liste:

new_items = [x if x % 2 else None for x in items]

Vous pouvez modifier la liste d'origine sur place si vous le souhaitez, mais cela ne fait pas gagner du temps:

items = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
for index, item in enumerate(items):
    if not (item % 2):
        items[index] = None

Voici les timings (Python 3.6.3) démontrant le non-timeave:

In [1]: %%timeit
   ...: items = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
   ...: for index, item in enumerate(items):
   ...:     if not (item % 2):
   ...:         items[index] = None
   ...:
1.06 µs ± 33.7 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each)

In [2]: %%timeit
   ...: items = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
   ...: new_items = [x if x % 2 else None for x in items]
   ...:
891 ns ± 13.6 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each)

Et les timings Python 2.7.6:

In [1]: %%timeit
   ...: items = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
   ...: for index, item in enumerate(items):
   ...:     if not (item % 2):
   ...:         items[index] = None
   ...: 
1000000 loops, best of 3: 1.27 µs per loop
In [2]: %%timeit
   ...: items = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
   ...: new_items = [x if x % 2 else None for x in items]
   ...: 
1000000 loops, best of 3: 1.14 µs per loop
156
John Millikin
ls = [x if (condition) else None for x in ls]
61

Répondant à une question posée par le PO dans un commentaire, à savoir:

et si j'avais un générateur qui donne les valeurs de la plage (11) au lieu de liste. Serait-il possible de remplacer valeurs dans le générateur?

Bien sûr, c'est trivialement facile ...:

def replaceiniter(it, predicate, replacement=None):
  for item in it:
    if predicate(item): yield replacement
    else: yield item

Il suffit de passer tout élément itérable (y compris le résultat de l'appel d'un générateur) en tant que premier argument, le prédicat permettant de décider si une valeur doit être remplacée en tant que second argument, et le laisser déchirer.

Par exemple:

>>> list(replaceiniter(xrange(11), lambda x: x%2))
[0, None, 2, None, 4, None, 6, None, 8, None, 10]
10
Alex Martelli

Voici un autre moyen:

>>> L = range (11)
>>> map(lambda x: x if x%2 else None, L)
[None, 1, None, 3, None, 5, None, 7, None, 9, None]
9
balpha
>>> L = range (11)
>>> [ x if x%2 == 1 else None for x in L ]
[None, 1, None, 3, None, 5, None, 7, None, 9, None]
2
eduffy

Si vous souhaitez remplacer des valeurs sur place, vous pouvez Mettre à jour votre liste d'origine avec les valeurs d'une liste Compréhension en affectant l'ensemble de la tranche de l'original.

data = [*range(11)] # [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
id_before = id(data)
data[:] = [x if x % 2 else None for x in data]
data
# Out: [None, 1, None, 3, None, 5, None, 7, None, 9, None]
id_before == id(data)  # check if list is still the same
# Out: True

Si vous avez plusieurs noms pointant vers la liste d'origine, par exemple, vous avez écrit data2=data avant de modifier la liste Et vous ignorez la notation de tranche pour l'attribution à data, data se reliera pour pointer vers la liste nouvellement créée tandis que data2 pointe toujours sur la liste originale non modifiée.

data = [*range(11)] # [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
data2 = data
id_before = id(data)
data = [x if x % 2 else None for x in data]  # no [:] here
data
# Out: [None, 1, None, 3, None, 5, None, 7, None, 9, None]
id_before == id(data)  # check if list is still the same
# Out: False
data2
# Out: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]

Remarque: Il ne s'agit pas d'une recommandation pour préférer en général une solution plutôt qu'une autre .__ (changement de liste en place ou non), mais un comportement que vous devriez connaître.

0
Darkonaut