2013-12-08 71 views
3

我見過很多關於如何在Python中扁平化列表的文章。但我從來沒有能夠明白這是如何工作的:reduce(lambda x,y:x+y,*myList)python中的扁平化列表

可能有人請解釋一下,這是如何工作的:

>>> myList = [[[1,2,3],[4,5],[6,7,8,9]]] 
>>> reduce(lambda x,y:x+y,*myList) 
[1, 2, 3, 4, 5, 6, 7, 8, 9] 
>>> 

聯體已經發布:

How to print list of list into one single list in python without using any for or while loop?

Flattening a shallow list in Python

Flatten (an irregular) list of lists

如果有人認爲這是重複的其他職位,我會刪除它,一旦我瞭解它是如何工作的。

謝謝。

+1

我試圖尋找它,但我想有人直接提供幫助:'* myList'中的'*'到底在做什麼?它如何基本消除'myList'中的外方括號? – SimonT

+1

@SimonT它被稱爲[序列拆包](http://docs.python.org/2/tutorial/controlflow.html#tut-unpacking-arguments) – aIKid

回答

4

什麼reduce呢,用簡單的英語,是它需要兩件事情:

  1. 函數f是:
    1. 準確接收2個參數
    2. 返回使用這兩個值
    3. 計算的值
  2. 可迭代的iter(例如liststr

reduce計算的f(iter[0],iter[1])(可迭代的前兩個項目)的結果,並跟蹤此值只是計算(稱之爲temp)的。 reduce然後計算f(temp,iter[2]),現在跟蹤這個新值。該過程繼續,直到iter中的每個項目都已傳遞到f,並返回計算出的最終值。

使用**myList轉換爲reduce函數的原因是它需要一個迭代器並將其轉換爲多個參數。這兩行做同樣的事情:

myFunc(10,12) 
myFunc(*[10,12]) 

myList的情況下,您使用的是list只包含只有一個list在裏面。因此,將*置於前面用myList[0]代替myList

關於兼容性,請注意reduce功能工作在Python 2完全正常,但在Python 3你就必須做到這一點:

import functools 
functools.reduce(some_iterable) 
+0

好問題。我只是嘗試'reduce(lambda x,y,z:x + y,* myList)'並且得到了TypeError:()缺少1個需要的位置參數:'z'。所以它看起來像函數必須有2個參數。 – SimonT

+0

謝謝你的解釋。 –

3

它等效於:

def my_reduce(func, seq, default=None): 
    it = iter(seq) 
    # assign either the first item from the iterable to x or the default value 
    # passed to my_reduce 
    x = next(it) if default is None else default 
    #For each item in iterable, update x by appying the function on x and y 
    for y in it: 
     x = func(x, y) 
    return x 
... 
>>> my_reduce(lambda a, b: a+b, *myList, default=[]) 
[1, 2, 3, 4, 5, 6, 7, 8, 9] 
>>> my_reduce(lambda a, b: a+b, *myList) 
[1, 2, 3, 4, 5, 6, 7, 8, 9] 
>>> from operator import add 
>>> my_reduce(add, *myList) 
[1, 2, 3, 4, 5, 6, 7, 8, 9] 
>>> my_reduce(lambda a, b: a+b, ['a', 'b', 'c', 'd']) 
'abcd' 

reduce文檔字符串有一個很好的解釋:

reduce(...) 
    reduce(function, sequence[, initial]) -> value 

    Apply a function of two arguments cumulatively to the items of a sequence, 
    from left to right, so as to reduce the sequence to a single value. 
    For example, reduce(lambda x, y: x+y, [1, 2, 3, 4, 5]) calculates 
    ((((1+2)+3)+4)+5). If initial is present, it is placed before the items 
    of the sequence in the calculation, and serves as a default when the 
    sequence is empty. 
+0

有趣的是,非常感謝你的帖子。 –

1

首先,我不知道爲什麼它包裹在一個數組,然後splatted(* )。這將同樣的方式工作:

>>> myList = [[1,2,3],[4,5],[6,7,8,9]] 
>>> reduce(lambda x,y:x+y,myList) 
[1, 2, 3, 4, 5, 6, 7, 8, 9] 

說明:reduce需要兩個參數的方法 - 累加器和元素。它調用每個元素的方法,然後將累加器設置爲lambda的結果。因此,您基本上將所有內部列表連接在一起。

這裏的一個一步一步的解釋:

  1. 累加器被初始化爲myList[0]這是[1,2,3]
  2. 拉姆達被調用[1,2,3][4,5],它返回[1,2,3,4,5],其被分配到累加器
  3. lambda被稱爲[1,2,3,4,5][6,7,8,9],它返回[1,2,3,4,5,6,7,8,9]
  4. 沒有更多的元素離開,所以reduce返回
+0

嗯,聽起來有趣,任何方式謝謝你的解釋。 –

2

首先,這是一個很不好方法。就這樣你知道。

reduce(f, [a, b, c, d])運行

f(f(f(f(a, b), c), d) 

由於flambda x,y:x+y,這相當於

((a + b) + c) + d 

對於名單,a + b是列表的級聯,所以這種連接每個列表。

這很慢,因爲每一步都要從頭開始創建一個新列表。