2009-08-20 5 views
302

Sto provando a mappare una lista in esadecimale, e quindi usare la lista altrove. In Python 2.6, questo è stato facile:Ottenere una mappa() per restituire una lista in Python 3.x

A: Python 2.6:

>>> map(chr, [66, 53, 0, 94]) 
['B', '5', '\x00', '^'] 

Tuttavia, in Python 3.1, il precedente restituisce un oggetto della mappa.

B: Python 3.1:

>>> map(chr, [66, 53, 0, 94]) 
<map object at 0x00AF5570> 

Come faccio a recuperare la lista mappata (come in A sopra) su Python 3.x?

In alternativa, c'è un modo migliore per farlo? Il mio oggetto lista iniziale ha circa 45 oggetti e id piace convertirli in esadecimale.

+0

@meawoppl vedere la mia risposta qui sotto http://stackoverflow.com/a/24507069/17523 –

risposta

462

fare questo:

list(map(chr,[66,53,0,94])) 

In Python 3+, molti processi che eseguono iterazioni su iterables restituiscono iteratori stessi. Nella maggior parte dei casi, questo finisce per risparmiare memoria e dovrebbe far andare le cose più velocemente.

Se tutto quello che stai andando a fare è di iterare su questo elenco alla fine, non c'è bisogno di convertire anche a un elenco, perché si può ancora scorrere sopra l'oggetto map in questo modo:

# Prints "ABCD" 
for ch in map(chr,[65,66,67,68]): 
    print(ch) 
+1

Grazie per l'ottima spiegazione !! – mozami

+10

Ovviamente, è possibile scorrere anche su questo: (chr (x) per x in [65,66,67,68]). Non ha nemmeno bisogno di una mappa. – hughdbrown

+0

@hughdbrown L'argomento per l'utilizzo di 3.La 'map' di 1 sarebbe una valutazione lazy quando si itera su una funzione complessa, grandi set di dati o flussi. –

70

Perché non state facendo questo:

[chr(x) for x in [66,53,0,94]] 

Si chiama una lista di comprensione. Puoi trovare molte informazioni su Google, ma here's the link to the Python (2.6) documentation on list comprehensions. Potresti essere più interessato a the Python 3 documenation, però.

+8

Sì per elencare le intese. – hughdbrown

+4

Hmmmm. Forse c'è bisogno di un post generale su list comprehensions, generators, map(), zip() e molta altra bontà di iterazione veloce in python. – hughdbrown

+23

Immagino perché è più verboso, devi scrivere una variabile extra (due volte) ... Se l'operazione è più complessa e finisci per scrivere un lambda, o devi anche lasciar cadere alcuni elementi, penso che una comprensione sia definitivamente meglio di una mappa + filtro, ma se hai già la funzione che desideri applicare, la mappa è più succinta. – fortran

11

I Non ho familiarità con Python 3.1, ma funzionerà?

[chr(x) for x in [66, 53, 0, 94]] 
+1

funziona perfettamente. – ExceptionSlayer

18

La funzione mappa di ritorno delle liste ha il vantaggio di salvare la digitazione, soprattutto durante le sessioni interattive. È possibile definire lmap funzione (in analogia python2 di imap) che restituisce la lista:

lmap = lambda func, *iterable: list(map(func, *iterable) 

quindi chiamando lmap invece di map farà il lavoro: lmap(str, x) è più corta di 5 caratteri (30% in questo caso) che list(map(str, x)) ed è sicuramente più breve di [str(v) for v in x]. È possibile creare funzioni simili anche per filter.

C'era un commento alla domanda iniziale:

Vorrei suggerire una ridenominazione di Getting mappa() per restituire un elenco in Python 3. * in quanto si applica a tutte le versioni python3. C'è un modo per fare questo? - meawoppl 24 gennaio alle 17:58

E è possibile farlo, ma è una pessima idea.Solo per divertimento, ecco come si può (ma non dovrebbe) fare:

__global_map = map #keep reference to the original map 
lmap = lambda func, *iterable: list(__global_map(func, *iterable)) # using "map" here will cause infinite recursion 
map = lmap 
x = [1, 2, 3] 
map(str, x) #test 
map = __global_map #restore the original map and don't do that again 
map(str, x) #iterator 
43

nuovo e pulito in Python 3.5:

[*map(chr, [66, 53, 0, 94])] 

Grazie alla Additional Unpacking Generalizations

+6

Cosa c'è di sbagliato con 'list()'? – Quelklef

+2

@Quelklef 'list()' non sembra pulito – Arijoon

+1

@Quelklef: Inoltre, l'approccio di decompressione è banalmente più veloce grazie alla non necessità di cercare il costruttore 'list' e di richiamare la macchina delle chiamate di funzioni generali. Per un input lungo, non importa; per un breve, può fare una grande differenza. Usando il codice sopra con l'input come una 'tupla' quindi non viene ripetutamente ricostruito, i microbenchmarks di' ipython' mostrano che l'approccio 'list()' wrapping richiede circa il 20% in più rispetto alla decompressione. Intendiamoci, in termini assoluti, stiamo parlando di 150 ns, che è banale, ma ti viene l'idea. – ShadowRanger

0
list(map(chr, [66, 53, 0, 94])) 

map (func, * iterables) -> map object Crea un iteratore che calcoli la funzione u cantare argomenti da ciascuno dei iterabili. Si ferma quando viene esaurito il breve iterabile.

"Crea un iteratore"

significa che restituirà un iteratore.

"che calcola la funzione utilizzando argomenti da ognuno dei iterables"

significa che la successiva funzione() dell'iteratore avrà un valore di ogni iterables e trasmettere ciascuno di essi di un posizionale parametro della funzione.

Quindi ottieni un iteratore dalla funzione map() e jsut passa alla funzione built-in list() o utilizza le list comprehensions.

1

Conversione my old comment per una migliore visibilità: per un "modo migliore per fare questo" senza map del tutto, se gli ingressi sono noti per essere ordinali ASCII, è generalmente molto più veloce per convertire in bytes e decodificare, alla bytes(list_of_ordinals).decode('ascii'). Questo ti dà un valore di str, ma se hai bisogno di un list per la mutevolezza o qualcosa di simile, puoi semplicemente convertirlo (ed è ancora più veloce). Per esempio, in ipython microbenchmarks conversione di 45 ingressi:

>>> %%timeit -r5 ordinals = list(range(45)) 
... list(map(chr, ordinals)) 
... 
3.91 µs ± 60.2 ns per loop (mean ± std. dev. of 5 runs, 100000 loops each) 

>>> %%timeit -r5 ordinals = list(range(45)) 
... [*map(chr, ordinals)] 
... 
3.84 µs ± 219 ns per loop (mean ± std. dev. of 5 runs, 100000 loops each) 

>>> %%timeit -r5 ordinals = list(range(45)) 
... [*bytes(ordinals).decode('ascii')] 
... 
1.43 µs ± 49.7 ns per loop (mean ± std. dev. of 5 runs, 1000000 loops each) 

>>> %%timeit -r5 ordinals = list(range(45)) 
... bytes(ordinals).decode('ascii') 
... 
781 ns ± 15.9 ns per loop (mean ± std. dev. of 5 runs, 1000000 loops each) 

Se si lascia come un str, ci vuole ~ 20% del tempo dei più veloci map soluzioni; anche convertendo di nuovo in elenco è ancora meno del 40% della più veloce soluzione map. convert Bulk via bytes e bytes.decode poi alla rinfusa La riconversione list consente di risparmiare un sacco di lavoro, ma come è noto, funziona solo se tutti gli ingressi sono ordinali ASCII (o ordinali in qualche un byte per codifica specifica localizzazione dei caratteri, per esempio latin-1).

Problemi correlati