簡體   English   中英

如何在python 3.4中使Maps和lambdas與矩陣一起工作?

[英]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']
  1. lambda (x, y): ''.join(x,y)是不合法的Python3。刪除了可迭代的參數拆包。 如果您實際運行的是您提到的版本上顯示的代碼,則將得到語法錯誤,而不是顯示的錯誤。

  2. 如果確實有一個描述的列表,而不是實際創建的列表,則需要給str.join一個可迭代的參數,而不是兩個參數,因此lambda (x, y): ''.join([x,y]) (類似於您顯示的代碼,但不是合法的Python 3),或更簡單地說,是lambda x_y: ''.join(x_y)

  3. 但是,這對您不起作用,因為str.join接受可迭代的字符串,並且在您的情況下,列表的結果列表為[ ['a', 1], ['a',2], ... ]而不是[ ['a', '1'], ['a','2'], ... ] 您不能以這種方式連接字符串和數字。 (這很好,因為str.join甚至不是正確的工作工具。)

  4. 使用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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM