简体   繁体   English

在python中展平列表

[英]Flattening list in python

I have seen many posts regarding how to flatten a list in Python. 我看过很多关于如何在Python中展平列表的帖子。 But I was never able to understand how this is working: reduce(lambda x,y:x+y,*myList) 但我无法理解这是如何工作的: reduce(lambda x,y:x+y,*myList)

Could someone please explain, how this is working: 有人可以解释,这是如何工作的:

>>> 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]
>>>

Linked already posted : 链接已发布:

How to print list of list into one single list in python without using any for or while loop? 如何在不使用任何for或while循环的情况下将列表列表打印到python中的单个列表中?

Flattening a shallow list in Python 在Python中展平浅层列表

Flatten (an irregular) list of lists 展平(不规则)列表列表

If anybody thinks this is duplicate to other post, I'll remove it once I understood how it works. 如果有人认为这与其他帖子重复,我会在理解它的工作原理后删除它。

Thanks. 谢谢。

What reduce does, in plain English, is that it takes two things: 简单来说, reduce是它需要两件事:

  1. A function f that: 一个函数f
    1. Accepts exactly 2 arguments 恰好接受2个参数
    2. Returns a value computed using those two values 返回使用这两个值计算的值
  2. An iterable iter (eg a list or str ) 可迭代的iter (例如liststr

reduce computes the result of f(iter[0],iter[1]) (the first two items of the iterable), and keeps track of this value that was just computed (call it temp ). reduce计算f(iter[0],iter[1])的结果f(iter[0],iter[1]) (可迭代的前两项),并跟踪刚刚计算的这个值(称之为temp )。 reduce then computes f(temp,iter[2]) and now keeps track of this new value. reduce然后计算f(temp,iter[2]) ,现在跟踪这个新值。 This process continues until every item in iter has been passed into f , and returns the final value computed. 这个过程一直持续到iter每个项都被传递给f ,并返回计算出的最终值。

The use of * in passing *myList into the reduce function is that it takes an iterable and turns it into multiple arguments. *myList传递给reduce函数时使用*是它需要一个可迭代的并将其转换为多个参数。 These two lines do the same thing: 这两行做同样的事情:

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

In the case of myList , you're using a list that contains only exactly one list in it. 对于myList ,您使用的list中只包含一个list For that reason, putting the * in front replaces myList with myList[0] . 因此,将*放在前面myList myList[0]替换为myList[0]

Regarding compatibility, note that the reduce function works totally fine in Python 2, but in Python 3 you'll have to do this: 关于兼容性,请注意reduce函数在Python 2中完全正常,但在Python 3中你必须这样做:

import functools
functools.reduce(some_iterable)

It is equivalent to : 它相当于:

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'

Docstring of reduce has a very good explanation: 文档字符串的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.

First of all, this is a very bad method. 首先,这是一个非常糟糕的方法。 Just so you know. 你知道吗

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

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

Since f is lambda x,y:x+y , this is equivalent to 由于flambda x,y:x+y ,这相当于

((a + b) + c) + d

For lists, a + b is the concatenation of the lists, so this joins each list. 对于列表, a + b是列表的串联,因此这将连接每个列表。

This is slow because each step has to make a new list from scratch. 这很慢,因为每个步骤都必须从头开始创建一个新列表。

First, I don't know why it's wrapped in an array and then splatted ( * ). 首先,我不知道为什么它被包裹在一个数组然后splatted( * )。 This will work the same way: 这将以相同的方式工作:

>>> 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]

Explanation: reduce takes a method with two parameters - the accumulator and the element. 说明: reduce接受一个带有两个参数的方法 - 累加器和元素。 It calls the method with each element and then sets the accumulator to the result of the lambda. 它使用每个元素调用方法,然后将累加器设置为lambda的结果。 Therefore, you're basically concatenating all the inner lists together. 因此,您基本上将所有内部列表连接在一起。

Here's a step-by-step explanation: 这是一步一步的解释:

  1. accumulator is initialized to myList[0] which is [1,2,3] accumulator初始化为myList[0] ,即[1,2,3]
  2. lambda is called with [1,2,3] and [4,5] , it returns [1,2,3,4,5] , which is assigned to the accumulator [1,2,3][4,5]调用lambda,它返回[1,2,3,4,5] ,它被赋值给累加器
  3. lambda is called with [1,2,3,4,5] and [6,7,8,9] , it returns [1,2,3,4,5,6,7,8,9] [1,2,3,4,5][6,7,8,9]调用lambda,它返回[1,2,3,4,5,6,7,8,9]
  4. no more elements left, so reduce returns that 没有剩下的元素,所以reduce返回

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM