[英]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.