Chiamare la funzione int () su ogni elemento dell'elenco?


184

Ho un elenco con stringhe numeriche, in questo modo:

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

Vorrei convertire tutti gli elementi dell'elenco in numeri interi, quindi sarebbe simile al seguente:

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

Potrei farlo usando un ciclo, in questo modo:

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

Deve essere così brutto? Sono sicuro che esiste un modo più pitonico per farlo in una riga di codice. Per favore aiutatemi.


1
Quale versione di Python stai usando?
Mark Byers,

Risposte:



131

In Python 2.x un altro approccio è usare map:

numbers = map(int, numbers)

Nota: in Python 3.x maprestituisce un oggetto mappa che è possibile convertire in un elenco se si desidera:

numbers = list(map(int, numbers))

11
In Python 3.x, maprestituisce un iteratore invece di un elenco, quindi deve essere scritto come list(map(int, numbers))se fosse necessario un elenco.
kennytm,

2
Penso che attualmente l'approccio alla comprensione dell'elenco sia un po 'più favorito.
extraneon

3
@extraneon: Sì ... o forse prendi in considerazione l'uso di un generatore anziché di un elenco, a seconda di cosa lo userai. Il vantaggio di un generatore è che se non hai bisogno di guardare tutti gli elementi, non dovrai perdere tempo a calcolarli in anticipo.
Mark Byers,

4
Misurato con timeit in Python 2.7.2: LC: 3.578153133392334, mappa: 4.9065070152282715
AJJ

1
@AJJ: mapha un overhead di installazione più elevato, ma sull'interprete di riferimento, se la funzione di trasformazione è una funzione integrata di Python implementata in C, ha un costo per articolo inferiore. Il test su un input di soli quattro valori non fornirà informazioni utili sul ridimensionamento. Detto questo, nei miei test (su Py2.7.12 e Py3.5.2, quest'ultimo con list()wrapping), Py2 ha mapvinto anche per input di quattro elementi e perde solo un piccolo margine su Py3; Sospetto che i tuoi test siano stati deformati a favore di listcomps.
ShadowRanger

21

solo un punto,

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

la comprensione dell'elenco è più naturale, mentre

numbers = map(int, numbers)

è più veloce.

Probabilmente questo non importerà nella maggior parte dei casi

Lettura utile: LP vs mappa


6
Non dovrebbe essere numero = mappa (int, numero)?
Karan,

9

Se si intende passare tali numeri interi a una funzione o a un metodo, considerare questo esempio:

sum(int(x) for x in numbers)

Questa costruzione è intenzionalmente notevolmente simile alla comprensione dell'elenco menzionata da Adamk. Senza le parentesi quadre, si chiama espressione del generatore ed è un modo molto efficiente in termini di memoria per passare un elenco di argomenti a un metodo. Una buona discussione è disponibile qui: espressioni dei generatori e comprensione delle liste


4

Un altro modo per farlo in Python 3:

numbers = [*map(int, numbers)]


1
Puoi spiegarlo? Non ho familiarità con quella sintassi. Grazie!
abalter il

1
Sto usando l'elenco degli argomenti di decompressione ( docs.python.org/3/tutorial/… )
zhukovgreen

Ah, una cosa di Python 3. Sembra strano aver []preso un elenco di argomenti. E non sapevo che potresti passare un iteratore come elenco di argomenti. Avrei pensato di fare number = list(map(int, numbers)). Ma grazie per la spiegazione!
abalter

3

Un altro modo,

for i, v in enumerate(numbers): numbers[i] = int(v)

6
OP ha detto pythonic
SilentGhost il

3
In questo modo è molto utile se si desidera eseguire l'operazione solo su alcuni degli elementi nell'elenco. Questo non è rilevante per la domanda in questo thread, ma possono esserci casi in cui è utile
Dikla,

1

Ho pensato di consolidare le risposte e mostrare alcuni timeitrisultati.

Python 2 fa davvero schifo, ma mapè un po 'più veloce della comprensione.

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 è 4 volte più veloce da solo, ma convertire l' mapoggetto generatore in un elenco è ancora più veloce della comprensione, e creare l'elenco scompattando il mapgeneratore (grazie Artem!) È ancora leggermente più veloce.

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

Nota: in Python 3, 4 elementi sembrano essere il punto di crossover (3 in Python 2) in cui la comprensione è leggermente più veloce, sebbene la decompressione del generatore sia ancora più veloce di quella per entrambi gli elenchi con più di 1 elemento.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.