I'm trying to map a list into hex, and then use the list elsewhere. In python 2.6, this was easy:
A: Python 2.6:
>>> map(chr, [66, 53, 0, 94])
['B', '5', '\x00', '^']
However, in Python 3.1, the above returns a map object.
B: Python 3.1:
>>> map(chr, [66, 53, 0, 94])
<map object at 0x00AF5570>
How do I retrieve the mapped list (as in A above) on Python 3.x?
Alternatively, is there a better way of doing this? My initial list object has around 45 items and id like to convert them to hex.
Use the list() class to convert a map object to a list, e.g. new_list = list(map(my_fuc, my_list)) . The list class takes an iterable (such as a map object) as an argument and returns a list object. Copied!
The map() function applies a given function to each item of an iterable (list, tuple etc.) and returns an iterator.
Python map() function iter : It is a iterable which is to be mapped. NOTE : You can pass one or more iterable to the map() function. Returns : Returns a list of the results after applying the given function to each item of a given iterable (list, tuple etc.)
Python map() Function The map() function executes a specified function for each item in an iterable. The item is sent to the function as a parameter.
Do this:
list(map(chr,[66,53,0,94]))
In Python 3+, many processes that iterate over iterables return iterators themselves. In most cases, this ends up saving memory, and should make things go faster.
If all you're going to do is iterate over this list eventually, there's no need to even convert it to a list, because you can still iterate over the map
object like so:
# Prints "ABCD"
for ch in map(chr,[65,66,67,68]):
print(ch)
New and neat in Python 3.5:
[*map(chr, [66, 53, 0, 94])]
Thanks to Additional Unpacking Generalizations
UPDATE
Always seeking for shorter ways, I discovered this one also works:
*map(chr, [66, 53, 0, 94]),
Unpacking works in tuples too. Note the comma at the end. This makes it a tuple of 1 element. That is, it's equivalent to (*map(chr, [66, 53, 0, 94]),)
It's shorter by only one char from the version with the list-brackets, but, in my opinion, better to write, because you start right ahead with the asterisk - the expansion syntax, so I feel it's softer on the mind. :)
Why aren't you doing this:
[chr(x) for x in [66,53,0,94]]
It's called a list comprehension. You can find plenty of information on Google, but here's the link to the Python (2.6) documentation on list comprehensions. You might be more interested in the Python 3 documenation, though.
List-returning map function has the advantage of saving typing, especially during interactive sessions. You can define lmap
function (on the analogy of python2's imap
) that returns list:
lmap = lambda func, *iterable: list(map(func, *iterable))
Then calling lmap
instead of map
will do the job:
lmap(str, x)
is shorter by 5 characters (30% in this case) than list(map(str, x))
and is certainly shorter than [str(v) for v in x]
. You may create similar functions for filter
too.
There was a comment to the original question:
I would suggest a rename to Getting map() to return a list in Python 3.* as it applies to all Python3 versions. Is there a way to do this? – meawoppl Jan 24 at 17:58
It is possible to do that, but it is a very bad idea. Just for fun, here's how you may (but should not) do it:
__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
Converting my old comment for better visibility: For a "better way to do this" without map
entirely, if your inputs are known to be ASCII ordinals, it's generally much faster to convert to bytes
and decode, a la bytes(list_of_ordinals).decode('ascii')
. That gets you a str
of the values, but if you need a list
for mutability or the like, you can just convert it (and it's still faster). For example, in ipython
microbenchmarks converting 45 inputs:
>>> %%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)
If you leave it as a str
, it takes ~20% of the time of the fastest map
solutions; even converting back to list it's still less than 40% of the fastest map
solution. Bulk convert via bytes
and bytes.decode
then bulk converting back to list
saves a lot of work, but as noted, only works if all your inputs are ASCII ordinals (or ordinals in some one byte per character locale specific encoding, e.g. latin-1
).
list(map(chr, [66, 53, 0, 94]))
map(func, *iterables) --> map object Make an iterator that computes the function using arguments from each of the iterables. Stops when the shortest iterable is exhausted.
"Make an iterator"
means it will return an iterator.
"that computes the function using arguments from each of the iterables"
means that the next() function of the iterator will take one value of each iterables and pass each of them to one positional parameter of the function.
So you get an iterator from the map() funtion and jsut pass it to the list() builtin function or use list comprehensions.
In addition to above answers in Python 3
, we may simply create a list
of result values from a map
as
li = []
for x in map(chr,[66,53,0,94]):
li.append(x)
print (li)
>>>['B', '5', '\x00', '^']
We may generalize by another example where I was struck, operations on map can also be handled in similar fashion like in regex
problem, we can write function to obtain list
of items to map and get result set at the same time. 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]
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With