问题:获取map()以在Python 3.x中返回列表
我正在尝试将列表映射为十六进制,然后在其他地方使用该列表。在python 2.6中,这很简单:
答: Python 2.6:
>>> map(chr, [66, 53, 0, 94])
['B', '5', '\x00', '^']
但是,在Python 3.1中,以上代码返回一个map对象。
B: Python 3.1:
>>> map(chr, [66, 53, 0, 94])
<map object at 0x00AF5570>
如何在Python 3.x上检索映射列表(如上面的A所示)?
另外,还有更好的方法吗?我的初始列表对象大约有45个项目,并且id喜欢将它们转换为十六进制。
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.
回答 0
做这个:
list(map(chr,[66,53,0,94]))
在Python 3+中,许多迭代可迭代对象的进程本身都会返回迭代器。在大多数情况下,这最终会节省内存,并且应该使处理速度更快。
如果您要做的只是最终遍历此列表,则无需将其转换为列表,因为您仍然可以map
像这样遍历该对象:
# Prints "ABCD"
for ch in map(chr,[65,66,67,68]):
print(ch)
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)
回答 1
Python 3.5的新功能:
[*map(chr, [66, 53, 0, 94])]
多亏了其他拆包概述
更新
一直在寻找更短的途径,我发现这也行得通:
*map(chr, [66, 53, 0, 94]),
开箱也适用于元组。注意最后的逗号。这使其成为1个元素的元组。也就是说,它相当于(*map(chr, [66, 53, 0, 94]),)
它比带有方括号的版本短一个字符,但我认为最好写,因为您从星号-扩展语法开始,所以我觉得它比较软。:)
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. :)
回答 2
回答 3
返回列表的地图功能具有保存键入的优点,尤其是在交互式会话期间。您可以定义返回列表的lmap
函数(类似于python2的函数imap
):
lmap = lambda func, *iterable: list(map(func, *iterable))
然后打电话 lmap
而不是即可map
完成工作:比
lmap(str, x)
短5个字符(在这种情况下为30%),list(map(str, x))
并且肯定比短[str(v) for v in x]
。您也可以创建类似的功能filter
。
对原始问题有一条评论:
我建议重命名为Geting map()以返回Python 3. *中的列表,因为它适用于所有Python3版本。有没有办法做到这一点?– meawoppl 1月24日17:58
这是有可能做到这一点,但它是一个非常糟糕的主意。只是为了好玩,您可以(但不应)执行以下操作:
__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
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
回答 4
将我的旧注释转换为更好的可见性:为了更好地“更好地做到这一点” map
,如果您的输入已知为ASCII序数,则通常可以更快地转换为bytes
la bytes(list_of_ordinals).decode('ascii')
。这样就可以得到一个str
值,但是如果您需要a list
来实现可变性或类似功能,则可以将其转换(并且转换速度仍然更快)。例如,在微ipython
基准中转换45个输入:
>>> %%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)
如果您将其保留为str
,则最快的map
解决方案会花费大约20%的时间;即使转换回列表,它仍然不到最快map
解决方案的40%。批量转换通过bytes
,bytes.decode
然后批量转换回以list
节省大量工作,但是如上所述,仅当您所有的输入都是ASCII序号(或每个字符特定于区域设置编码的字节中的序号latin-1
)时,该方法才有效。
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
).
回答 5
list(map(chr, [66, 53, 0, 94]))
map(func,* iterables)->地图对象创建一个迭代器,该迭代器使用每个可迭代对象的参数来计算函数。当最短的迭代次数用尽时停止。
“进行迭代”
表示它将返回迭代器。
“使用每个可迭代对象的参数来计算函数”
意味着迭代器的next()函数将为每个可迭代对象取一个值,并将每个值传递给该函数的一个位置参数。
因此,您可以从map()函数中获得一个迭代器,然后jsut将其传递给内置函数list()或使用列表推导。
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.
回答 6
除了上述答案外Python 3
,我们还可以简单地list
从map
as中创建结果值a
li = []
for x in map(chr,[66,53,0,94]):
li.append(x)
print (li)
>>>['B', '5', '\x00', '^']
我们可以通过另一个例子来概括我被打动的情况,对地图的操作也可以像regex
问题中一样的方式处理,我们可以编写函数以获取list
要映射的项目并同时获取结果集。例如
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]
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]
回答 7
您可以尝试通过仅迭代对象中的每个项目并将其存储在另一个变量中来从地图对象获取列表。
a = map(chr, [66, 53, 0, 94])
b = [item for item in a]
print(b)
>>>['B', '5', '\x00', '^']
You can try getting a list from the map object by just iterating each item in the object and store it in a different variable.
a = map(chr, [66, 53, 0, 94])
b = [item for item in a]
print(b)
>>>['B', '5', '\x00', '^']
回答 8
使用python中的列表理解和基本的地图函数实用程序,还可以做到这一点:
chi = [x for x in map(chr,[66,53,0,94])]
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])]