Appelez la fonction int () sur chaque élément de la liste?

188

J'ai une liste avec des chaînes numériques, comme ceci:

numbers = ['1', '5', '10', '8'];

Je voudrais convertir chaque élément de la liste en entier, donc cela ressemblerait à ceci:

numbers = [1, 5, 10, 8];

Je pourrais le faire en utilisant une boucle, comme ceci:

new_numbers = [];
for n in numbers:
    new_numbers.append(int(n));
numbers = new_numbers;

Doit-il être si moche? Je suis sûr qu'il existe une manière plus pythonique de faire cela en une seule ligne de code. Sil te plait aide moi.

Lumière argentée
la source
1
Quelle version de Python utilisez-vous?
Mark Byers

Réponses:

136

En Python 2.x, une autre approche consiste à utiliser map:

numbers = map(int, numbers)

Remarque: en Python 3.x maprenvoie un objet de carte que vous pouvez convertir en liste si vous le souhaitez:

numbers = list(map(int, numbers))
Mark Byers
la source
11
Dans Python 3.x, maprenvoie un itérateur au lieu d'une liste, il doit donc être écrit comme list(map(int, numbers))si une liste était nécessaire.
kennytm
2
Je pense qu'actuellement, l'approche de compréhension de liste est un peu plus favorisée.
extraneon le
3
@extraneon: Ouais ... ou peut-être envisager d'utiliser un générateur au lieu d'une liste, en fonction de l'utilisation que vous en ferez. L'avantage d'un générateur est que si vous n'avez pas besoin de regarder tous les éléments, vous n'aurez pas à perdre de temps à les calculer à l'avance.
Mark Byers
4
Mesuré avec timeit sous Python 2.7.2: LC: 3.578153133392334, carte: 4.9065070152282715
AJJ
1
@AJJ: mapa une surcharge de configuration plus élevée, mais sur l'interpréteur de référence, si la fonction de transformation est une fonction intégrée Python implémentée en C, elle a un coût par élément inférieur. Tester sur une entrée de seulement quatre valeurs ne fournira pas d'informations utiles sur la mise à l'échelle. Cela dit, dans mes propres tests (sur Py2.7.12 et Py3.5.2, ce dernier avec list()wrapping), Py2 a mapgagné même pour quatre entrées d'élément, et ne perd que d'une infime marge sur Py3; Je soupçonne que vos tests ont été faussés en faveur des listcomps.
ShadowRanger
23

juste un point,

numbers = [int(x) for x in numbers]

la compréhension de la liste est plus naturelle, tandis que

numbers = map(int, numbers)

est plus rapide.

Cela n'aura probablement pas d'importance dans la plupart des cas

Lecture utile: LP vs carte

renatopp
la source
6
Ne devrait-il pas être number = map (int, number)?
Karan
9

Si vous avez l'intention de transmettre ces entiers à une fonction ou une méthode, considérez cet exemple:

sum(int(x) for x in numbers)

Cette construction est intentionnellement remarquablement similaire aux compréhensions de listes mentionnées par Adamk. Sans les crochets, c'est ce qu'on appelle une expression de générateur , et c'est un moyen très efficace en mémoire de passer une liste d'arguments à une méthode. Une bonne discussion est disponible ici: Expressions de générateur vs compréhension de liste

Tim McNamara
la source
5

Une autre façon de le faire en Python 3:

numbers = [*map(int, numbers)]

zhukovgreen
la source
1
Pouvez-vous expliquer cela? Je ne connais pas cette syntaxe. Merci!
abalter
1
J'utilise la liste des arguments de déballage ( docs.python.org/3/tutorial/… )
zhukovgreen
Aha, une chose python 3. Cela semble étrange d'avoir []pris une liste d'arguments. Et je ne savais pas que vous pouviez passer un itérateur comme liste d'arguments. J'aurais pensé faire number = list(map(int, numbers)). Mais merci pour l'explication!
abalter
3

Autrement,

for i, v in enumerate(numbers): numbers[i] = int(v)
Nick Dandoulakis
la source
6
OP said pythonic
SilentGhost
3
Cette méthode est très utile si vous souhaitez exécuter l'opération uniquement sur certains des éléments de la liste. Ce n'est pas pertinent pour la question dans ce fil, mais il peut y avoir des cas où cela est utile
Dikla
1

Je pensais que je consoliderais les réponses et montrerais quelques timeitrésultats.

Python 2 est plutôt mauvais à cela, mais mapest un peu plus rapide que la compréhension.

Python 2.7.13 (v2.7.13:a06454b1afa1, Dec 17 2016, 20:42:59) [MSC v.1500 32 bit (Intel)] on win32
Type "copyright", "credits" or "license()" for more information.
>>> import timeit
>>> setup = """import random
random.seed(10)
l = [str(random.randint(0, 99)) for i in range(100)]"""
>>> timeit.timeit('[int(v) for v in l]', setup)
116.25092001434314
>>> timeit.timeit('map(int, l)', setup)
106.66044823117454

Python 3 est plus de 4x plus rapide en lui-même, mais la conversion de l' mapobjet générateur en liste est toujours plus rapide que la compréhension, et la création de la liste en décompressant le mapgénérateur (merci Artem!) Est encore légèrement plus rapide.

Python 3.6.1 (v3.6.1:69c0db5, Mar 21 2017, 17:54:52) [MSC v.1900 32 bit (Intel)] on win32
Type "copyright", "credits" or "license()" for more information.
>>> import timeit
>>> setup = """import random
random.seed(10)
l = [str(random.randint(0, 99)) for i in range(100)]"""
>>> timeit.timeit('[int(v) for v in l]', setup)
25.133059591551955
>>> timeit.timeit('list(map(int, l))', setup)
19.705547827217515
>>> timeit.timeit('[*map(int, l)]', setup)
19.45838406513076

Remarque: Dans Python 3, 4 éléments semblent être le point de croisement (3 en Python 2) où la compréhension est légèrement plus rapide, bien que le déballage du générateur soit toujours plus rapide que pour les listes avec plus d'un élément.

Jim
la source