web-dev-qa-db-fra.com

Obtenir une carte () pour retourner une liste dans Python 3.x

J'essaie de mapper une liste dans un hex, puis d'utiliser la liste ailleurs. En python 2.6, c'était facile:

A: Python 2.6:

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

Cependant, dans Python 3.1, ce qui précède renvoie un objet de carte.

B: Python 3.1:

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

Comment récupérer la liste mappée (comme dansAci-dessus) sur Python 3.x? 

Sinon, y a-t-il une meilleure façon de faire cela? Mon objet de liste initial contient environ 45 éléments et son identifiant est de les convertir en hexadécimal.

409
mozami

Faire ceci:

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

En Python 3+, de nombreux processus qui itèrent sur des itérables renvoient des itérateurs eux-mêmes. Dans la plupart des cas, cela économise de la mémoire et devrait accélérer les choses. 

Si vous ne faites que parcourir la liste ultérieurement, vous n'avez même pas besoin de la convertir en liste, car vous pouvez toujours effectuer une itération sur l'objet map comme suit:

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

Pourquoi ne faites-vous pas ceci:

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

Cela s'appelle une compréhension de liste. Vous pouvez trouver de nombreuses informations sur Google, mais voici le lien vers la documentation Python (2.6) sur les compréhensions de liste . Vous pourriez être plus intéressé par la documentation de Python 3 , cependant.

86
Mark Rushakoff

Nouveau et soigné dans Python 3.5:

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

Merci à Autres généralisations de décompression

METTRE &AGRAVE; JOUR

Toujours à la recherche de solutions plus courtes, j'ai découvert que celui-ci fonctionnait également:

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

Le déballage fonctionne aussi en tuples. Notez la virgule à la fin. Cela en fait un tuple de 1 élément. Autrement dit, cela équivaut à (*map(chr, [66, 53, 0, 94]),)

Il est plus court d'un seul caractère de la version avec les crochets de liste, mais, à mon avis, il est préférable d'écrire, car vous commencez tout droit avec l'astérisque - la syntaxe de développement, ce qui me semble plus doux pour l'esprit. :)

71
Israel Unterman

La fonction de mappage avec retour de liste présente l’avantage d’enregistrer les saisies, en particulier lors de sessions interactives. Vous pouvez définir la fonction lmap (sur l'analogie du imap de python2) qui renvoie la liste:

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

Ensuite, appeler lmap au lieu de map fera l'affaire: lmap(str, x) est plus court de 5 caractères (30% dans ce cas) que list(map(str, x)) et est certainement plus court que [str(v) for v in x]. Vous pouvez également créer des fonctions similaires pour filter.

Il y avait un commentaire à la question initiale:

Je suggérerais de renommer Getting map () pour renvoyer une liste dans Python 3. * comme cela s'applique à toutes les versions de Python3. Y a-t-il un moyen de faire cela? - Meawoppl le 24 janvier à 17:58

C'est est possible de le faire, mais c'est une très mauvaise idée. Juste pour le plaisir, voici comment vous pouvez ( mais ne devriez pas ) le faire:

__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
20
Boris Gorelik

Je ne connais pas Python 3.1, mais cela fonctionnera-t-il?

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

Convertir mon vieux commentaire pour une meilleure visibilité: Pour une "meilleure façon de faire cela" sans map entièrement, si vos entrées sont connues pour être des ordinaux ASCII, il est généralement beaucoup plus rapide de convertir en bytes et de décoder, a la bytes(list_of_ordinals).decode('ascii'). Cela vous donne une str des valeurs, mais si vous avez besoin d'une list pour la mutabilité ou similaire, vous pouvez simplement la convertir (et c'est encore plus rapide). Par exemple, dans ipython microbenchmarks convertissant 45 entrées:

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

Si vous le laissez comme str, cela prend environ 20% du temps des solutions map les plus rapides; Même en revenant à la liste, il reste moins de 40% de la solution map la plus rapide. La conversion en bloc via bytes et bytes.decode, puis la conversion en vrac en list enregistre beaucoup de travail. Mais comme indiqué, ne fonctionne que si toutes vos entrées sont des ordinaux ASCII (ou des ordinaux dans un octet par caractère, en fonction des paramètres régionaux encodage, par exemple latin-1).

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

map (func, * iterables) -> objet map Créez un itérateur qui calcule la fonction en utilisant les arguments de chacun des iterables. S'arrête lorsque le plus court terme est épuisé.

"Faire un itérateur"

signifie qu'il retournera un itérateur.

"qui calcule la fonction en utilisant des arguments de chacun des iterables"

signifie que la fonction next () de l'itérateur prendra une valeur de chaque itérable et passera chacune d'elles à un paramètre de position de la fonction.

Donc, vous obtenez un itérateur de la fonction map () et le transmettez à la fonction intégrée list () ou utilisez la compréhension de liste.

0
Ini

En plus des réponses ci-dessus dans Python 3, nous pouvons simplement créer une list de valeurs de résultat à partir d'une map comme 

li = []
for x in map(chr,[66,53,0,94]):
    li.append(x)

print (li)
>>>['B', '5', '\x00', '^']

Nous pouvons généraliser par un autre exemple où j'ai été frappé, les opérations sur la carte peuvent également être gérées de la même manière que dans le problème regex, nous pouvons écrire une fonction pour obtenir list d'éléments à mapper et obtenir le résultat en même temps. 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]
0
Harry_pb