2012-09-27 26 views
2

我想寫一個像zip一樣的函數。我不擅長解釋我的意思,所以我只會顯示我想要做的事情的「代碼」。Python深拉鍊

a = [1,2,3,[4,5]] 
b = a[:] 
zip(a, b) == [(1,1), (2,2), (3,3), ([4,5],[4,5])] 
myzip(a, b) == [(1,1), (2,2), (3,3), [(4,4), (5,5)]] 

我很困難,這甚至不好笑。我試圖用遞歸lambdas以簡單的函數式編寫它,以使我的代碼更漂亮。我想myzip喜歡這樣,因爲我想用它的輸出與其它功能我寫了一個函數映射到一棵樹

def tree_map(func, tree): 
    return map(lambda x: func(x) if not isinstance(x, list) else tree_map(func, x), 
       tree) 

我一直在試圖做類似這樣的帶拉鍊的東西,但我似乎無法把我的頭包裹起來。有沒有人有任何想法,我怎麼可以寫myzip?

編輯:看看tree_map!是不是很漂亮!我至少這麼認爲,但我的母語是Scheme:P ,同時我也希望myzip能夠儘可能深入。基本上,我希望myzip保留通過它的樹的結構。此外,myzip只能處理相同形狀的樹木。

+0

「我試圖用遞歸lambdas以簡單的函數式方式編寫它,以使我的代碼更漂亮。」這就像......好吧,不,我不會試圖想出一些喜劇性的比喻。但是lambda表達式的遞歸不太可能讓你的代碼更漂亮。 – DSM

+0

只是2級的好,還是必須是無限的? – jterrace

+1

你有沒有想過檢查['itertools'](http://docs.python.org/library/itertools.html#itertools.izip)?有一些Python僞代碼呈現可以激發你的邏輯...... –

回答

7

我認爲有以下應該工作:

import collections 

def myzip(*args): 
    if all(isinstance(arg, collections.Iterable) for arg in args): 
     return [myzip(*vals) for vals in zip(*args)] 
    return args 

結果:

>>> a = [1,2,3,[4,[5,6]]] 
>>> b = [1,2,3,[4,[5,6]]] 
>>> myzip(a, b) 
[(1, 1), (2, 2), (3, 3), [(4, 4), [(5, 5), (6, 6)]]] 

注意,我在類型檢查使用collections.Iterable,而不是list,這樣的行爲更像是zip()與元組和其他迭代。

+0

令人驚歎!!!!!!太棒了!!!我想,如果沒有幾天想到這一點,那將花費我幾個小時。謝謝! – Broseph

+0

簡單美麗。 –

+0

+1。你可能想要堅持所有的參數都是列表,而不僅僅是第一個參數,所以你可以做一些合理的事情(比如一個扁平的拉鍊)而不是一個例外......除非當然這不應該是有效的,在這種情況下,例外是完美的。此外,你可能想使用'collections.Iterable'而不是列表(所以它可以深入壓縮元組等)。甚至把整個事情寫成一個迭代器而不是一個列表。但是,這是有效的,它很好,很簡單。 – abarnert