By mozami


2009-08-20 00:27:26 8 Comments

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.

9 comments

@darshan k s 2018-11-11 16:57:14

Using list comprehension in python and basic map function utility, one can do this also:

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

@darshan k s 2018-11-11 17:01:17

chi list will be containing, the ASIC value of the given elements.

@Israel Unterman 2016-08-01 15:18:41

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. :)

@Quelklef 2017-08-12 12:56:13

What's wrong with list()?

@Arijoon 2017-09-28 13:15:47

@Quelklef list() doesn't look as neat

@ShadowRanger 2017-11-08 04:41:41

@Quelklef: Also, the unpacking approach is trivially faster thanks to not needing to look up the list constructor and invoke general function call machinery. For a long input, it won't matter; for a short one, it can make a big difference. Using the above code with the input as a tuple so it's not repeatedly reconstructed, ipython microbenchmarks show the list() wrapping approach takes about 20% longer than unpacking. Mind you, in absolute terms, we're talking about 150 ns, which is trivial, but you get the idea.

@Giorgio 2018-10-26 20:04:06

What was wrong with the old map? Maybe with a new name (lmap?) if the new default is to return an iterator?

@ALH 2018-12-22 12:38:46

*map() gives syntax error on Python 3.6: can't use starred expression here. You need to put it in a list: [ *map() ]

@LondonRob 2019-01-20 19:11:33

@ALH You missed the comma on the end of the command. Easy mistake to make!

@Harry_pb 2018-06-15 16:35:30

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]

@Harry_pb 2018-06-15 17:32:43

@miradulo I supposed in Python 2, a list was returned, but in Python 3, only type is returned and I just tried to give in same format. If you think its needless, there maybe people like me who can find it useful and thats why I added.

@miradulo 2018-06-15 20:04:09

When there is already a list comprehension, a list function, and an unpacking answer, an explicit for loop doesn’t add much IMHO.

@Boris Gorelik 2014-07-01 09:41:21

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

@ShadowRanger 2017-11-08 04:52:46

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

@Ini 2017-11-07 09:04:30

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.

@Triptych 2009-08-20 00:28:40

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)

@hughdbrown 2009-08-20 00:40:19

Of course, you can iterate over this, too: (chr(x) for x in [65,66,67,68]). It doesn't even need map.

@Andrew Keeton 2009-08-20 00:45:11

@hughdbrown The argument for using 3.1's map would be lazy evaluation when iterating on a complex function, large data sets, or streams.

@Triptych 2009-08-20 00:49:49

@Andrew actually Hugh is uing a generator comprehension which would do the same thing. Note the parentheses rather than square brackets.

@ShadowRanger 2016-07-01 01:52:22

Alternate solution (faster for large inputs too) when the values are known to be ASCII/latin-1 is to do bulk conversions at the C layer: bytes(sequence_of_ints_in_range_0_to_256).decode('latin-1') which makes a str faster by avoiding Python function calls for each element in favor of a bulk conversion of all elements using only C level function calls. You can wrap the above in list if you really need a list of the individual characters, but since str is already an iterable of its own characters, the only reason you'd do so is if you need mutability.

@peterb 2016-08-15 12:16:48

This is super useful information. I was wondering what happened to the map :)

@Andor 2016-09-07 10:13:39

list(map(str, [1,2,3])) gives "Error in argument" for Python 3.4.3 on CentOS 7. List comprehension works.

@Andor 2016-09-07 10:21:16

The "Error in argument" occures only in PDB debugger. See: stackoverflow.com/questions/17290314/…

@Giorgio 2018-10-26 19:56:55

"In Python 3+, many processes that iterate over iterables return iterators themselves.": But in Python 2 there is imap and ifilter, so the new semantics of map and filter is not new, it is just the old semantics of imap and ifilter with a new name. So have map and filter returning a list been dropped completely? Having to add an extra call to list looks like unnecessary boilerplate to me.

@Mark Rushakoff 2009-08-20 00:28:19

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.

@hughdbrown 2009-08-20 00:29:41

Yes to list comprehensions.

@hughdbrown 2009-08-20 00:55:13

Hmmmm. Maybe there needs to be a general posting on list comprehensions, generators, map(), zip(), and a lot of other speedy iteration goodness in python.

@fortran 2010-06-25 09:43:15

I guess because it's more verbose, you have to write an extra variable (twice)... If the operation is more complex and you end up writing a lambda, or you need also to drop some elements, I think a comprehension is definitively better than a map+filter, but if you already have the function you want to apply, map is more succinct.

@Le Droid 2014-03-06 21:55:52

+1: Easier to read & allows you to use functions with many parameters

@Giorgio 2018-10-26 20:01:20

map(chr, [66,53,0,94]) is definitely more concise than [chr(x) for x in [66,53,0,94]].

@Andrew Keeton 2009-08-20 00:28:44

I'm not familiar with Python 3.1, but will this work?

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

Related Questions

Sponsored Content

56 Answered Questions

[SOLVED] Calling an external command in Python

30 Answered Questions

[SOLVED] How do I check if a list is empty?

  • 2008-09-10 06:20:11
  • Ray Vega
  • 2271313 View
  • 3236 Score
  • 30 Answer
  • Tags:   python list

20 Answered Questions

11 Answered Questions

[SOLVED] Getting the last element of a list

  • 2009-05-30 19:28:53
  • Janusz
  • 1660558 View
  • 1712 Score
  • 11 Answer
  • Tags:   python list indexing

7 Answered Questions

[SOLVED] How do I get the number of elements in a list?

  • 2009-11-11 00:30:54
  • y2k
  • 3085855 View
  • 1786 Score
  • 7 Answer
  • Tags:   python list

39 Answered Questions

[SOLVED] How to make a flat list out of list of lists

25 Answered Questions

[SOLVED] How do I concatenate two lists in Python?

21 Answered Questions

15 Answered Questions

[SOLVED] What are metaclasses in Python?

28 Answered Questions

[SOLVED] Finding the index of an item given a list containing it in Python

  • 2008-10-07 01:39:38
  • Eugene M
  • 3289684 View
  • 2708 Score
  • 28 Answer
  • Tags:   python list indexing

Sponsored Content