[英]How do I make Maps and lambdas work with a matrix in python 3.4?
我经常避免写这样的文章,但是我是python 3.4的新手,我需要有关此代码的帮助。
假设我们有以下列表:
v = [ [ x, y ] for x in ['a','b','c'] for y in range(1,5) ]
结果列表列表:[['a','1'],['a','2'],...]
现在,我想加入那些字符串。 我尝试了以下方法:
p = map(lambda (x, y): ''.join(x,y), v)
没用
错误:
TypeError: join() takes exactly one argument (2 given)
我试图在文档中查找,但是我不能解决我的问题。
有人有主意吗?
你可以做:
>>> list(map(lambda x: ''.join(map(str, x)), v))
['a1', 'a2', 'a3', 'a4', 'b1', 'b2', 'b3', 'b4', 'c1', 'c2', 'c3', 'c4']
这将为v
每个元素执行函数lambda x: ''.join(map(str, x))
。 v
的元素是一个列表,其中包含一个字符串和一个整数作为值。 这意味着由lambda
函数接收的x
是具有这两个值的列表。
然后,在将它们传递到join()
之前,我们需要确保该列表中的所有值都是字符串。 这意味着我们将调用map(str, x)
将子列表x
中的所有值转换为字符串( ['a', 1]
变为['a', '1']
)。 然后,我们可以通过将结果传递给''.join(...)
( ['a', '1']
成为['a1']
)来加入它们。 对v
每个列表执行此操作,因此可以给我们所需的结果。
map
的结果是Python 3.x中所谓的mapobject
,因此我们将所有内容包装在list()
调用中以得到一个列表。
同样,列表理解在这里可以说更具可读性:
>>> [x[0] + str(x[1]) for x in v]
['a1', 'a2', 'a3', 'a4', 'b1', 'b2', 'b3', 'b4', 'c1', 'c2', 'c3', 'c4']
lambda (x, y): ''.join(x,y)
是不合法的Python3。删除了可迭代的参数拆包。 如果您实际运行的是您提到的版本上显示的代码,则将得到语法错误,而不是显示的错误。
如果确实有一个描述的列表,而不是实际创建的列表,则需要给str.join
一个可迭代的参数,而不是两个参数,因此lambda (x, y): ''.join([x,y])
(类似于您显示的代码,但不是合法的Python 3),或更简单地说,是lambda x_y: ''.join(x_y)
但是,这对您不起作用,因为str.join
接受可迭代的字符串,并且在您的情况下,列表的结果列表为[ ['a', 1], ['a',2], ... ]
而不是[ ['a', '1'], ['a','2'], ... ]
。 您不能以这种方式连接字符串和数字。 (这很好,因为str.join
甚至不是正确的工作工具。)
使用map
+ lambda
总是很愚蠢。 只要在所有情况下都使用生成器表达式,就可以使用map
+ lambda
请参阅以下示例(我使用列表推导而不是生成器表达式,因此我们将获得有用的代表):
py> v = [ [ x, y ] for x in ['a','b','c'] for y in range(1,5) ]
py> [''.join([let, num]) for let, num in v]
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 1, in <listcomp>
TypeError: sequence item 1: expected str instance, int found
py> ['{}{}'.format(let, num) for let, num in v]
['a1', 'a2', 'a3', 'a4', 'b1', 'b2', 'b3', 'b4', 'c1', 'c2', 'c3', 'c4']
如果您仅需要连接一定数量的元素,则可以使用str.format :
print(list(map(lambda x: "{}{}".format(*x) , v)))
['a1', 'a2', 'a3', 'a4', 'b1', 'b2', 'b3', 'b4', 'c1', 'c2', 'c3', 'c4']
您还可以使用"{}" * len(x)
对任意数量的元素进行处理:
print(list(map(lambda x: ("{}" * len(x)).format(*x) , v)))
*x
解压缩序列, "{}" * len(x)
为每个子列表中的每个元素创建一个{}
。
或解压缩列表组件:
print([ "{}{}".format(*x) for x in v])
我同意Mike的观点, map(lambda
是愚蠢的。在这种情况下, '{}{}'.format
几乎可以完成lambda应该执行的工作,因此您可以改用它:
starmap('{}{}'.format, v)
那使用了itertools.starmap
。 如果要使用map
,可以这样进行:
map('{}{}'.format, *zip(*v))
但是我真的会做
(c + str(n) for c, n in v)
编辑:map + lambda与generator表达式的比较,显示后者更短,更清晰,更灵活(解压缩)和更快:
>>> from timeit import timeit
>>> r = range(10000000)
>>> timeit(lambda: sum(map(lambda xy: xy[0]+xy[1], zip(r, r))), number=1)
7.221420832748007
>>> timeit(lambda: sum(x+y for x, y in zip(r, r)), number=1)
5.192609298897533
>>> timeit(lambda: sum(map(lambda x: 2*x, r)), number=1)
5.870139625224283
>>> timeit(lambda: sum(2*x for x in r), number=1)
4.4056527464802
>>> r = range(10)
>>> timeit(lambda: sum(map(lambda xy: xy[0]+xy[1], zip(r, r))), number=1000000)
7.047922363577214
>>> timeit(lambda: sum(x+y for x, y in zip(r, r)), number=1000000)
4.78059718055448
您可以使用另一个列表理解:
>>> [''.join((x, str(y))) for x, y in v]
['a1', 'a2', 'a3', 'a4', 'b1', 'b2', 'b3', 'b4', 'c1', 'c2', 'c3', 'c4']
如果不需要v
,则可以在第一个列表理解中执行:
>>> [''.join((x, str(y))) for x in ['a','b','c'] for y in range(1,5)]
['a1', 'a2', 'a3', 'a4', 'b1', 'b2', 'b3', 'b4', 'c1', 'c2', 'c3', 'c4']
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.