Een kaart krijgen () om een ​​lijst in Python 3.x

Ik probeer een lijst in de hex in kaart te brengen en gebruik vervolgens de lijst elders. In Python 2.6 was dit eenvoudig:

A: Python 2.6:

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

In Python 3.1 retourneert het bovenstaande een kaartobject.

B: Python 3.1:

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

Hoe haal ik de toegewezen lijst op (zoals in A hierboven) op Python 3.x?

Als alternatief, is er een betere manier om dit te doen? Mijn initiële lijstobject heeft ongeveer 45 items en id om ze te converteren naar HEX.


Antwoord 1, Autoriteit 100%

Doe dit:

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

In Python 3+, vele processen die herhoogden over iterables, retourneren iterators zelf. In de meeste gevallen eindigt dit het opslaan van het geheugen en moet het sneller gaan.

Als alles wat u gaat doen, is het uiteindelijk over deze lijst, het is niet nodig om het zelfs naar een lijst te converteren, omdat u nog steeds over de mapobject zoals SO:

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

Antwoord 2, Autoriteit 17%

Nieuw en netjes in Python 3.5:

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

Dank aan extra uitpakkende generalisaties

update

Altijd op zoek naar kortere manieren, ontdekte ik dat deze ook werkt:

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

Uitpakken werkt ook in tupels. Let op de komma aan het einde. Dit maakt het een tupel van 1 element. Dat wil zeggen, het is gelijk aan (*map(chr, [66, 53, 0, 94]),)

Het is slechts één teken korter dan de versie met de lijst-haakjes, maar naar mijn mening is het beter om te schrijven, omdat je meteen begint met de asterisk – de uitbreidingssyntaxis, dus ik voel dat het zachter is. 🙂


Antwoord 3, autoriteit 13%

Waarom doe je dit niet:

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

Het wordt een lijstbegrip genoemd. Je kunt veel informatie vinden op Google, maar hier is de link naar de Python (2.6) documentatie over lijstbegrippen. Misschien ben je echter meer geïnteresseerd in de Python 3-documentatie.


Antwoord 4, autoriteit 3%

Lijst-terugkerende kaartfunctie heeft het voordeel dat typen wordt bespaard, vooral tijdens interactieve sessies. U kunt de functie lmapdefiniëren (naar analogie van imapvan python2) die lijst retourneert:

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

Dan zal het aanroepen van lmapin plaats van maphet werk doen:
lmap(str, x)is korter met 5 tekens (30% in dit geval) dan list(map(str, x))en is zeker korter dan [str(v) for v in x]. U kunt vergelijkbare functies voor filterook maken.

Er was een opmerking voor de oorspronkelijke vraag:

Ik zou een hernoemen voorstellen om kaart te krijgen () om een ​​lijst in Python te retourneren 3. * Aangezien het van toepassing is op alle Python3-versies. Is er een manier om dit te doen? – MEAWOPPL 24 januari om 17:58

IT is mogelijk om dat te doen, maar het is een heel slecht idee. Gewoon voor de lol, hier is hoe je (maar mag ) doen:

__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

Antwoord 5

Converteren mijn oude Reactie voor een betere zichtbaarheid: voor een “betere manier om dit te doen” zonder mapvolledig, als uw ingangen bekend zijn als ASCII-ordinals, is het over het algemeen veel sneller om te converteren naar bytesEN DECODE, A LA bytes(list_of_ordinals).decode('ascii'). Dat krijgt u een strvan de waarden, maar als u een listnodig hebt voor mutabiliteit of dergelijke, kunt u het gewoon converteren (en het is nog steeds sneller). Bijvoorbeeld in ipythonMicrobenchmarks Converteren 45 ingangen:

>>> %%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)

Als je het als een strlaat staan, duurt het ~20% van de tijd van de snelste map-oplossingen; zelfs terug naar lijst converteren is nog steeds minder dan 40% van de snelste map-oplossing. Bulkconversie via bytesen bytes.decodeen vervolgens bulkconversie terug naar listbespaart veel werk, maarals opgemerkt, werkt alleen als al uw invoer ASCII-ordinalen zijn (of ordinalen in een lokale specifieke codering van één byte per teken, bijv. latin-1).


Antwoord 6

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

map(func, *iterables) –> kaart object
Maak een iterator die de functie berekent met behulp van argumenten van
elk van de iterables. Stopt wanneer de kortste iterable is uitgeput.

“Maak een iterator”

betekent dat het een iterator teruggeeft.

“die de functie berekent met behulp van argumenten uit elk van de iterables”

betekent dat de next() functie van de iterator één waarde van elke iterable zal nemen en elk van hen zal doorgeven aan één positionele parameter van de functie.

Dus je krijgt een iterator van de map()-functie en geeft deze gewoon door aan de ingebouwde functie list() of je gebruikt lijstbegrippen.


Antwoord 7

In aanvulling op de bovenstaande antwoorden in Python 3, kunnen we eenvoudig een listmet resultaatwaarden maken van een mapals

li = []
for x in map(chr,[66,53,0,94]):
    li.append(x)
print (li)
>>>['B', '5', '\x00', '^']

We kunnen generaliseren met een ander voorbeeld waar ik werd getroffen, bewerkingen op de kaart kunnen ook op dezelfde manier worden afgehandeld, zoals in het regex-probleem, we kunnen een functie schrijven om listte verkrijgen van items om in kaart te brengen en tegelijkertijd een resultaatset te krijgen. Ex.

b = 'Strings: 1,072, Another String: 474 '
li = []
for x in map(int,map(int, re.findall('\d+', b))):
    li.append(x)
print (li)
>>>[1, 72, 474]

Antwoord 8

Je kunt proberen een lijst van het kaartobject te krijgen door elk item in het object te herhalen en het in een andere variabele op te slaan.

a = map(chr, [66, 53, 0, 94])
b = [item for item in a]
print(b)
>>>['B', '5', '\x00', '^']

Antwoord 9

Een andere optie is om een snelkoppeling te maken en een lijst terug te geven:

from functools import reduce
_compose = lambda f, g: lambda *args: f(g(*args))
lmap = reduce(_compose, (list, map))
>>> lmap(chr, [66, 53, 0, 94])
['B', '5', '\x00', '^']

Antwoord 10

Met behulp van lijstbegrip in python en het basishulpprogramma voor kaartfuncties, kan men dit ook doen:

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

Other episodes