如何从列表列表中列出平面列表?

发布于 2025-01-21 06:58:38 字数 493 浏览 3 评论 0 原文

我有一个列表列表,例如

[
    [1, 2, 3],
    [4, 5, 6],
    [7],
    [8, 9]
]

如何将其弄平以获得 [1,2,2,3,4,5,6,7,8,9]


如果您的列表来自嵌套列表的理解,则可以通过修复理解力来更简单/直接解决该问题;请参阅我如何从列表理解而不是嵌套列表中获得平坦的结果?

这里最受欢迎的解决方案通常只会使嵌套列表的一个“级别”变平。参见平列列表列表的不规则(任意嵌套)列表对于完全嵌入深度嵌套结构的解决方案(一般而言,一般而言)。 /sub>

I have a list of lists like

[
    [1, 2, 3],
    [4, 5, 6],
    [7],
    [8, 9]
]

How can I flatten it to get [1, 2, 3, 4, 5, 6, 7, 8, 9]?


If your list of lists comes from a nested list comprehension, the problem can be solved more simply/directly by fixing the comprehension; please see How can I get a flat result from a list comprehension instead of a nested list?.

The most popular solutions here generally only flatten one "level" of the nested list. See Flatten an irregular (arbitrarily nested) list of lists for solutions that completely flatten a deeply nested structure (recursively, in general).

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(30

喜爱纠缠 2025-01-28 06:58:38

名为 XSS 的列表可以使用嵌套列表理解

flat_list = [
    x
    for xs in xss
    for x in xs
]

以上等效于:

flat_list = []

for xs in xss:
    for x in xs:
        flat_list.append(x)

这是相应的函数:

def flatten(xss):
    return [x for xs in xss for x in xs]

这​​是最快的方法。
作为证据,使用 timeit timeit 标准中的模块库,我们会看到:

$ python -mtimeit -s'xss=[[1,2,3],[4,5,6],[7],[8,9]]*99' '[x for xs in xss for x in xs]'
10000 loops, best of 3: 143 usec per loop

$ python -mtimeit -s'xss=[[1,2,3],[4,5,6],[7],[8,9]]*99' 'sum(xss, [])'
1000 loops, best of 3: 969 usec per loop

$ python -mtimeit -s'xss=[[1,2,3],[4,5,6],[7],[8,9]]*99' 'reduce(lambda xs, ys: xs + ys, xss)'
1000 loops, best of 3: 1.1 msec per loop

说明:基于+的方法(包括 sum 中的隐含用途)是必要的, o(l ** 2)< /code>当有l子列表时 - 随着中级结果列表的越来越长,在每个步骤中,新的中间结果列表对象都会分配,并且必须复制上一个中级结果中的所有项目(以及一些(以及一些)最终添加了新的)。因此,为简单起见,没有实际的一般性丧失,请假设您有每个项目的子列表。 -2 次,依此类推;副本的总数是x的x总和,x的总和从1到l排除,即, m*(l ** 2)/2

列表理解只会生成一个列表,一次将每个项目(从其原始的居住地到结果列表)都精确地复制。

A list of lists named xss can be flattened using a nested list comprehension:

flat_list = [
    x
    for xs in xss
    for x in xs
]

The above is equivalent to:

flat_list = []

for xs in xss:
    for x in xs:
        flat_list.append(x)

Here is the corresponding function:

def flatten(xss):
    return [x for xs in xss for x in xs]

This is the fastest method.
As evidence, using the timeit module in the standard library, we see:

$ python -mtimeit -s'xss=[[1,2,3],[4,5,6],[7],[8,9]]*99' '[x for xs in xss for x in xs]'
10000 loops, best of 3: 143 usec per loop

$ python -mtimeit -s'xss=[[1,2,3],[4,5,6],[7],[8,9]]*99' 'sum(xss, [])'
1000 loops, best of 3: 969 usec per loop

$ python -mtimeit -s'xss=[[1,2,3],[4,5,6],[7],[8,9]]*99' 'reduce(lambda xs, ys: xs + ys, xss)'
1000 loops, best of 3: 1.1 msec per loop

Explanation: the methods based on + (including the implied use in sum) are, of necessity, O(L**2) when there are L sublists -- as the intermediate result list keeps getting longer, at each step a new intermediate result list object gets allocated, and all the items in the previous intermediate result must be copied over (as well as a few new ones added at the end). So, for simplicity and without actual loss of generality, say you have L sublists of M items each: the first M items are copied back and forth L-1 times, the second M items L-2 times, and so on; total number of copies is M times the sum of x for x from 1 to L excluded, i.e., M * (L**2)/2.

The list comprehension just generates one list, once, and copies each item over (from its original place of residence to the result list) also exactly once.

物价感观 2025-01-28 06:58:38

您可以使用 itertools.chains.chain()

>>> import itertools
>>> list2d = [[1,2,3], [4,5,6], [7], [8,9]]
>>> merged = list(itertools.chain(*list2d))

或者您可以使用 itertoolss.chain.from_iterables.chain.from_iterable()代码> 不需要用*运算符解开列表:

>>> import itertools
>>> list2d = [[1,2,3], [4,5,6], [7], [8,9]]
>>> merged = list(itertools.chain.from_iterable(list2d))

此方法可以说是比 [sublist in l for sublist中的lim s for sublist in in sublist中的项目] 并且似乎也更快:

$ python3 -mtimeit -s'l=[[1,2,3],[4,5,6], [7], [8,9]]*99;import itertools' 'list(itertools.chain.from_iterable(l))'
20000 loops, best of 5: 10.8 usec per loop
$ python3 -mtimeit -s'l=[[1,2,3],[4,5,6], [7], [8,9]]*99' '[item for sublist in l for item in sublist]'
10000 loops, best of 5: 21.7 usec per loop
$ python3 -mtimeit -s'l=[[1,2,3],[4,5,6], [7], [8,9]]*99' 'sum(l, [])'
1000 loops, best of 5: 258 usec per loop
$ python3 -mtimeit -s'l=[[1,2,3],[4,5,6], [7], [8,9]]*99;from functools import reduce' 'reduce(lambda x,y: x+y,l)'
1000 loops, best of 5: 292 usec per loop
$ python3 --version
Python 3.7.5rc1

You can use itertools.chain():

>>> import itertools
>>> list2d = [[1,2,3], [4,5,6], [7], [8,9]]
>>> merged = list(itertools.chain(*list2d))

Or you can use itertools.chain.from_iterable() which doesn't require unpacking the list with the * operator:

>>> import itertools
>>> list2d = [[1,2,3], [4,5,6], [7], [8,9]]
>>> merged = list(itertools.chain.from_iterable(list2d))

This approach is arguably more readable than [item for sublist in l for item in sublist] and appears to be faster too:

$ python3 -mtimeit -s'l=[[1,2,3],[4,5,6], [7], [8,9]]*99;import itertools' 'list(itertools.chain.from_iterable(l))'
20000 loops, best of 5: 10.8 usec per loop
$ python3 -mtimeit -s'l=[[1,2,3],[4,5,6], [7], [8,9]]*99' '[item for sublist in l for item in sublist]'
10000 loops, best of 5: 21.7 usec per loop
$ python3 -mtimeit -s'l=[[1,2,3],[4,5,6], [7], [8,9]]*99' 'sum(l, [])'
1000 loops, best of 5: 258 usec per loop
$ python3 -mtimeit -s'l=[[1,2,3],[4,5,6], [7], [8,9]]*99;from functools import reduce' 'reduce(lambda x,y: x+y,l)'
1000 loops, best of 5: 292 usec per loop
$ python3 --version
Python 3.7.5rc1
徒留西风 2025-01-28 06:58:38

作者的注释:这非常效率低下。但是很有趣,因为 monoids 很棒。

>>> xss = [[1, 2, 3], [4, 5, 6], [7], [8, 9]]
>>> sum(xss, [])
[1, 2, 3, 4, 5, 6, 7, 8, 9]

sum 总和峰值 xss ,并将第二个参数用作总和的初始值 [] 。 (默认的初始值是 0 ,不是列表。)

由于您要求和列表,因此您实际上获得 [1,3]+[2,4] >由于 sum([[1,3],[2,4]],[])等于 [1,3,2,4]

请注意,仅在列表列表上工作。对于列表列表的列表,您需要另一个解决方案。

Note from the author: This is very inefficient. But fun, because monoids are awesome.

>>> xss = [[1, 2, 3], [4, 5, 6], [7], [8, 9]]
>>> sum(xss, [])
[1, 2, 3, 4, 5, 6, 7, 8, 9]

sum sums the elements of the iterable xss, and uses the second argument as the initial value [] for the sum. (The default initial value is 0, which is not a list.)

Because you are summing nested lists, you actually get [1,3]+[2,4] as a result of sum([[1,3],[2,4]],[]), which is equal to [1,3,2,4].

Note that only works on lists of lists. For lists of lists of lists, you'll need another solution.

凉风有信 2025-01-28 06:58:38

我用),发现

import functools
import operator
functools.reduce(operator.iconcat, a, [])

是最快的解决方案,当许多小列表和很少的长列表被加入时。 ( operator.iadd 同样快。)

一个更简单且可接受的变体是,

out = []
for sublist in a:
    out.extend(sublist)

如果统一的数量较大,则其性能比上述建议差一些。

”在此处输入图像描述”


代码重现图:

import functools
import itertools
import operator

import numpy as np
import perfplot


def forfor(a):
    return [item for sublist in a for item in sublist]


def sum_brackets(a):
    return sum(a, [])


def functools_reduce(a):
    return functools.reduce(operator.concat, a)


def functools_reduce_iconcat(a):
    return functools.reduce(operator.iconcat, a, [])


def itertools_chain(a):
    return list(itertools.chain.from_iterable(a))


def numpy_flat(a):
    return list(np.array(a).flat)


def numpy_concatenate(a):
    return list(np.concatenate(a))


def extend(a):
    out = []
    for sublist in a:
        out.extend(sublist)
    return out


b = perfplot.bench(
    setup=lambda n: [list(range(10))] * n,
    # setup=lambda n: [list(range(n))] * 10,
    kernels=[
        forfor,
        sum_brackets,
        functools_reduce,
        functools_reduce_iconcat,
        itertools_chain,
        numpy_flat,
        numpy_concatenate,
        extend,
    ],
    n_range=[2 ** k for k in range(16)],
    xlabel="num lists (of length 10)",
    # xlabel="len lists (10 lists total)"
)
b.save("out.png")
b.show()

I tested most suggested solutions with perfplot (a pet project of mine, essentially a wrapper around timeit), and found

import functools
import operator
functools.reduce(operator.iconcat, a, [])

to be the fastest solution, both when many small lists and few long lists are concatenated. (operator.iadd is equally fast.)

A simpler and also acceptable variant is

out = []
for sublist in a:
    out.extend(sublist)

If the number of sublists is large, this performs a little worse than the above suggestion.

enter image description here

enter image description here


Code to reproduce the plot:

import functools
import itertools
import operator

import numpy as np
import perfplot


def forfor(a):
    return [item for sublist in a for item in sublist]


def sum_brackets(a):
    return sum(a, [])


def functools_reduce(a):
    return functools.reduce(operator.concat, a)


def functools_reduce_iconcat(a):
    return functools.reduce(operator.iconcat, a, [])


def itertools_chain(a):
    return list(itertools.chain.from_iterable(a))


def numpy_flat(a):
    return list(np.array(a).flat)


def numpy_concatenate(a):
    return list(np.concatenate(a))


def extend(a):
    out = []
    for sublist in a:
        out.extend(sublist)
    return out


b = perfplot.bench(
    setup=lambda n: [list(range(10))] * n,
    # setup=lambda n: [list(range(n))] * 10,
    kernels=[
        forfor,
        sum_brackets,
        functools_reduce,
        functools_reduce_iconcat,
        itertools_chain,
        numpy_flat,
        numpy_concatenate,
        extend,
    ],
    n_range=[2 ** k for k in range(16)],
    xlabel="num lists (of length 10)",
    # xlabel="len lists (10 lists total)"
)
b.save("out.png")
b.show()
儭儭莪哋寶赑 2025-01-28 06:58:38

使用 XS 添加到下一个列表 ys

from functools import reduce
xss = [[1,2,3], [4,5,6], [7], [8,9]]
out = reduce(lambda xs, ys: xs + ys, xss)

输出:

[1, 2, 3, 4, 5, 6, 7, 8, 9]

使用 operator.concat

from functools import reduce
import operator
xss = [[1,2,3], [4,5,6], [7], [8,9]]
out = reduce(operator.concat, xss)

输出:输出:

[1, 2, 3, 4, 5, 6, 7, 8, 9]

Using functools.reduce, which adds an accumulated list xs to the next list ys:

from functools import reduce
xss = [[1,2,3], [4,5,6], [7], [8,9]]
out = reduce(lambda xs, ys: xs + ys, xss)

Output:

[1, 2, 3, 4, 5, 6, 7, 8, 9]

A faster way using operator.concat:

from functools import reduce
import operator
xss = [[1,2,3], [4,5,6], [7], [8,9]]
out = reduce(operator.concat, xss)

Output:

[1, 2, 3, 4, 5, 6, 7, 8, 9]
与风相奔跑 2025-01-28 06:58:38

这是一种适用于嵌套混合容器的对象(例如数字 )的一般方法。这可能会使简单和复杂的容器变平(另请参见 emo )。

代码

from typing import Iterable 
#from collections import Iterable                            # < py38


def flatten(items):
    """Yield items from any nested iterable; see Reference."""
    for x in items:
        if isinstance(x, Iterable) and not isinstance(x, (str, bytes)):
            for sub_x in flatten(x):
                yield sub_x
        else:
            yield x

注释

  • 在python 3中, flatten(x)可以替换flatten(x)中的sub_x的:sub_x
  • in Python 3.8, collection.abc 移动 键入模块。

demo

simple = [[1, 2, 3], [4, 5, 6], [7], [8, 9]]
list(flatten(simple))
# [1, 2, 3, 4, 5, 6, 7, 8, 9]

complicated = [[1, [2]], (3, 4, {5, 6}, 7), 8, "9"]              # numbers, strs, nested & mixed
list(flatten(complicated))
# [1, 2, 3, 4, 5, 6, 7, 8, '9']

参考

  • 该解决方案是根据 beazley,D。和B. Jones中的配方修改的。食谱4.14,Python食谱第三版,O'Reilly Media Inc. Sebastopol,CA:2013。
  • 找到了一个较早的,可能是原始演示。

Here is a general approach that applies to objects (e.g. numbers, strings) in nested and mixed containers. This can flatten both simple and complicated containers (see also Demo).

Code

from typing import Iterable 
#from collections import Iterable                            # < py38


def flatten(items):
    """Yield items from any nested iterable; see Reference."""
    for x in items:
        if isinstance(x, Iterable) and not isinstance(x, (str, bytes)):
            for sub_x in flatten(x):
                yield sub_x
        else:
            yield x

Notes:

  • In Python 3, yield from flatten(x) can replace for sub_x in flatten(x): yield sub_x
  • In Python 3.8, abstract base classes are moved from collection.abc to the typing module.

Demo

simple = [[1, 2, 3], [4, 5, 6], [7], [8, 9]]
list(flatten(simple))
# [1, 2, 3, 4, 5, 6, 7, 8, 9]

complicated = [[1, [2]], (3, 4, {5, 6}, 7), 8, "9"]              # numbers, strs, nested & mixed
list(flatten(complicated))
# [1, 2, 3, 4, 5, 6, 7, 8, '9']

Reference

  • This solution is modified from a recipe in Beazley, D. and B. Jones. Recipe 4.14, Python Cookbook 3rd Ed., O'Reilly Media Inc. Sebastopol, CA: 2013.
  • Found an earlier SO post, possibly the original demonstration.
浮生未歇 2025-01-28 06:58:38

要使一个深层嵌套的数据实现,请使用 iteratory_utilitys_utilitys。 deepflatten 1

>>> from iteration_utilities import deepflatten

>>> l = [[1, 2, 3], [4, 5, 6], [7], [8, 9]]
>>> list(deepflatten(l, depth=1))
[1, 2, 3, 4, 5, 6, 7, 8, 9]

>>> l = [[1, 2, 3], [4, [5, 6]], 7, [8, 9]]
>>> list(deepflatten(l))
[1, 2, 3, 4, 5, 6, 7, 8, 9]

它是一个生成器,因此您需要将结果施加到 list 或明确迭代它。


要使一个级别的级别弄平,如果每个项目本身都具有峰值,则还可以使用 iteration_utilities.flatten 本身只是 itertools.chain.from_iterable

>>> from iteration_utilities import flatten
>>> l = [[1, 2, 3], [4, 5, 6], [7], [8, 9]]
>>> list(flatten(l))
[1, 2, 3, 4, 5, 6, 7, 8, 9]

只是添加一些时间(基于 nicoschlömer的答案不包括此答案中呈现的功能):

这是一个日志图,可容纳跨越庞大的值。对于定性推理:较低是更好的。

结果表明,如果峰值仅包含几个内部迭代物品,则 sum 将是最快的,但是对于长期迭代而言,仅 itertools.chains.chain.from_iterable iteration_utilities。 DeepFlatten 或嵌套的理解性具有合理的性能, itertools.chain.from_iterable 是最快的(正如NicoSchlömer已经注意到的那样)。

from itertools import chain
from functools import reduce
from collections import Iterable  # or from collections.abc import Iterable
import operator
from iteration_utilities import deepflatten

def nested_list_comprehension(lsts):
    return [item for sublist in lsts for item in sublist]

def itertools_chain_from_iterable(lsts):
    return list(chain.from_iterable(lsts))

def pythons_sum(lsts):
    return sum(lsts, [])

def reduce_add(lsts):
    return reduce(lambda x, y: x + y, lsts)

def pylangs_flatten(lsts):
    return list(flatten(lsts))

def flatten(items):
    """Yield items from any nested iterable; see REF."""
    for x in items:
        if isinstance(x, Iterable) and not isinstance(x, (str, bytes)):
            yield from flatten(x)
        else:
            yield x

def reduce_concat(lsts):
    return reduce(operator.concat, lsts)

def iteration_utilities_deepflatten(lsts):
    return list(deepflatten(lsts, depth=1))


from simple_benchmark import benchmark

b = benchmark(
    [nested_list_comprehension, itertools_chain_from_iterable, pythons_sum, reduce_add,
     pylangs_flatten, reduce_concat, iteration_utilities_deepflatten],
    arguments={2**i: [[0]*5]*(2**i) for i in range(1, 13)},
    argument_name='number of inner lists'
)

b.plot()

1免责声明:我是该图书馆的作者

To flatten a data-structure that is deeply nested, use iteration_utilities.deepflatten1:

>>> from iteration_utilities import deepflatten

>>> l = [[1, 2, 3], [4, 5, 6], [7], [8, 9]]
>>> list(deepflatten(l, depth=1))
[1, 2, 3, 4, 5, 6, 7, 8, 9]

>>> l = [[1, 2, 3], [4, [5, 6]], 7, [8, 9]]
>>> list(deepflatten(l))
[1, 2, 3, 4, 5, 6, 7, 8, 9]

It's a generator so you need to cast the result to a list or explicitly iterate over it.


To flatten only one level and if each of the items is itself iterable you can also use iteration_utilities.flatten which itself is just a thin wrapper around itertools.chain.from_iterable:

>>> from iteration_utilities import flatten
>>> l = [[1, 2, 3], [4, 5, 6], [7], [8, 9]]
>>> list(flatten(l))
[1, 2, 3, 4, 5, 6, 7, 8, 9]

Just to add some timings (based on Nico Schlömer's answer that didn't include the function presented in this answer):

Enter image description here

It's a log-log plot to accommodate for the huge range of values spanned. For qualitative reasoning: Lower is better.

The results show that if the iterable contains only a few inner iterables then sum will be fastest, however for long iterables only the itertools.chain.from_iterable, iteration_utilities.deepflatten or the nested comprehension have reasonable performance with itertools.chain.from_iterable being the fastest (as already noticed by Nico Schlömer).

from itertools import chain
from functools import reduce
from collections import Iterable  # or from collections.abc import Iterable
import operator
from iteration_utilities import deepflatten

def nested_list_comprehension(lsts):
    return [item for sublist in lsts for item in sublist]

def itertools_chain_from_iterable(lsts):
    return list(chain.from_iterable(lsts))

def pythons_sum(lsts):
    return sum(lsts, [])

def reduce_add(lsts):
    return reduce(lambda x, y: x + y, lsts)

def pylangs_flatten(lsts):
    return list(flatten(lsts))

def flatten(items):
    """Yield items from any nested iterable; see REF."""
    for x in items:
        if isinstance(x, Iterable) and not isinstance(x, (str, bytes)):
            yield from flatten(x)
        else:
            yield x

def reduce_concat(lsts):
    return reduce(operator.concat, lsts)

def iteration_utilities_deepflatten(lsts):
    return list(deepflatten(lsts, depth=1))


from simple_benchmark import benchmark

b = benchmark(
    [nested_list_comprehension, itertools_chain_from_iterable, pythons_sum, reduce_add,
     pylangs_flatten, reduce_concat, iteration_utilities_deepflatten],
    arguments={2**i: [[0]*5]*(2**i) for i in range(1, 13)},
    argument_name='number of inner lists'
)

b.plot()

1 Disclaimer: I'm the author of that library

风流物 2025-01-28 06:58:38

以下对我来说似乎最简单:

>>> import numpy as np
>>> l = [[1, 2, 3], [4, 5, 6], [7], [8, 9]]
>>> print(np.concatenate(l))
[1 2 3 4 5 6 7 8 9]

The following seems simplest to me:

>>> import numpy as np
>>> l = [[1, 2, 3], [4, 5, 6], [7], [8, 9]]
>>> print(np.concatenate(l))
[1 2 3 4 5 6 7 8 9]
¢好甜 2025-01-28 06:58:38

考虑安装 more_itertools 软件包。

> pip install more_itertools

它带有 source a href =“ https://docs.python.org/3/library/itertools.html#itertools-recipes” rel =“ noreferrer”> itertools配方):

import more_itertools


lst = [[1, 2, 3], [4, 5, 6], [7], [8, 9]]
list(more_itertools.flatten(lst))
# [1, 2, 3, 4, 5, 6, 7, 8, 9]

注意:注意:注意: a href =“ https://more-itertools.readthedocs.io/en/stable/pi.html#more_itertools.flatten” rel =“ noreferrer”> docs , flatten 需要一个列表列表。请参阅下面的关于更加不规则输入的内容。


在版本2.4时,您可以使用 more_itertools.collapse source ,由abarnet贡献)。

lst = [[1, 2, 3], [4, 5, 6], [7], [8, 9]]
list(more_itertools.collapse(lst)) 
# [1, 2, 3, 4, 5, 6, 7, 8, 9]

lst = [[1, 2, 3], [[4, 5, 6]], [[[7]]], 8, 9]              # complex nesting
list(more_itertools.collapse(lst))
# [1, 2, 3, 4, 5, 6, 7, 8, 9]

Consider installing the more_itertools package.

> pip install more_itertools

It ships with an implementation for flatten (source, from the itertools recipes):

import more_itertools


lst = [[1, 2, 3], [4, 5, 6], [7], [8, 9]]
list(more_itertools.flatten(lst))
# [1, 2, 3, 4, 5, 6, 7, 8, 9]

Note: as mentioned in the docs, flatten requires a list of lists. See below on flattening more irregular inputs.


As of version 2.4, you can flatten more complicated, nested iterables with more_itertools.collapse (source, contributed by abarnet).

lst = [[1, 2, 3], [4, 5, 6], [7], [8, 9]]
list(more_itertools.collapse(lst)) 
# [1, 2, 3, 4, 5, 6, 7, 8, 9]

lst = [[1, 2, 3], [[4, 5, 6]], [[[7]]], 8, 9]              # complex nesting
list(more_itertools.collapse(lst))
# [1, 2, 3, 4, 5, 6, 7, 8, 9]
眼前雾蒙蒙 2025-01-28 06:58:38

根据您的列表 [[1,2,3],[4,5,6],[7],[8,9]] 是1个列表级别,我们可以简单地使用 sum(list,[]),无需使用任何库

sum([[1, 2, 3], [4, 5, 6], [7], [8, 9]],[])
# [1, 2, 3, 4, 5, 6, 7, 8, 9]

时,就可以扩展此方法的优势。只需通过 map 添加每个元素的映射函数

#For only tuple
sum(list(map(list,[[1, 2, 3], (4, 5, 6), (7,), [8, 9]])),[])
# [1, 2, 3, 4, 5, 6, 7, 8, 9]

#In general

def convert(x):
    if type(x) is int or type(x) is float:
           return [x]
    else:
           return list(x)

sum(list(map(convert,[[1, 2, 3], (4, 5, 6), 7, [8, 9]])),[])
# [1, 2, 3, 4, 5, 6, 7, 8, 9]

在这里,关于这种方法的记忆,对缺点有一个明确的解释。简而言之,它递归创建列表对象,应避免使用:(

According your list [[1, 2, 3], [4, 5, 6], [7], [8, 9]] which is 1 list level, we can simply use sum(list,[]) without using any libraries

sum([[1, 2, 3], [4, 5, 6], [7], [8, 9]],[])
# [1, 2, 3, 4, 5, 6, 7, 8, 9]

To extend the advantage of this method when there is a tuple or number existing inside. Simply adding a mapping function for each element by map to the list

#For only tuple
sum(list(map(list,[[1, 2, 3], (4, 5, 6), (7,), [8, 9]])),[])
# [1, 2, 3, 4, 5, 6, 7, 8, 9]

#In general

def convert(x):
    if type(x) is int or type(x) is float:
           return [x]
    else:
           return list(x)

sum(list(map(convert,[[1, 2, 3], (4, 5, 6), 7, [8, 9]])),[])
# [1, 2, 3, 4, 5, 6, 7, 8, 9]

In here, there is a clear explanation of the drawback in terms of memory for this approach. In short, it recursively creates list objects, which should be avoided :(

故事还在继续 2025-01-28 06:58:38

您的函数无法使用的原因是,扩展 将数组在就位且不会返回。您仍然可以使用这样的东西从lambda返回X:

reduce(lambda x,y: x.extend(y) or x, l)

注意:扩展比列表上的 + + + +更有效。

The reason your function didn't work is because the extend extends an array in-place and doesn't return it. You can still return x from lambda, using something like this:

reduce(lambda x,y: x.extend(y) or x, l)

Note: extend is more efficient than + on lists.

随梦而飞# 2025-01-28 06:58:38

matplotlib.cbook.flatten()即使它们比示例更深,它们也将适用于嵌套列表。

import matplotlib
l = [[1, 2, 3], [4, 5, 6], [7], [8, 9]]
print(list(matplotlib.cbook.flatten(l)))
l2 = [[1, 2, 3], [4, 5, 6], [7], [8, [9, 10, [11, 12, [13]]]]]
print(list(matplotlib.cbook.flatten(l2)))

结果:

[1, 2, 3, 4, 5, 6, 7, 8, 9]
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13]

这比下划线快18倍._。扁平:

Average time over 1000 trials of matplotlib.cbook.flatten: 2.55e-05 sec
Average time over 1000 trials of underscore._.flatten: 4.63e-04 sec
(time for underscore._)/(time for matplotlib.cbook) = 18.1233394636

matplotlib.cbook.flatten() will work for nested lists even if they nest more deeply than the example.

import matplotlib
l = [[1, 2, 3], [4, 5, 6], [7], [8, 9]]
print(list(matplotlib.cbook.flatten(l)))
l2 = [[1, 2, 3], [4, 5, 6], [7], [8, [9, 10, [11, 12, [13]]]]]
print(list(matplotlib.cbook.flatten(l2)))

Result:

[1, 2, 3, 4, 5, 6, 7, 8, 9]
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13]

This is 18x faster than underscore._.flatten:

Average time over 1000 trials of matplotlib.cbook.flatten: 2.55e-05 sec
Average time over 1000 trials of underscore._.flatten: 4.63e-04 sec
(time for underscore._)/(time for matplotlib.cbook) = 18.1233394636
似狗非友 2025-01-28 06:58:38

一个人还可以使用numpy的

import numpy as np
list(np.array(l).flat)

flat当标准师具有相同维度时的作品。

One can also use NumPy's flat:

import numpy as np
list(np.array(l).flat)

It only works when sublists have identical dimensions.

圈圈圆圆圈圈 2025-01-28 06:58:38

您可以使用 list 扩展方法。它表明是最快的:

flat_list = []
for sublist in l:
    flat_list.extend(sublist)

性能:

import functools
import itertools
import numpy
import operator
import perfplot


def functools_reduce_iconcat(a):
    return functools.reduce(operator.iconcat, a, [])


def itertools_chain(a):
    return list(itertools.chain.from_iterable(a))


def numpy_flat(a):
    return list(numpy.array(a).flat)


def extend(a):
    n = []

    list(map(n.extend, a))

    return n


perfplot.show(
    setup = lambda n: [list(range(10))] * n,
    kernels = [
        functools_reduce_iconcat, extend, itertools_chain, numpy_flat
        ],
    n_range = [2**k for k in range(16)],
    xlabel = 'num lists',
    )

输出:

“在此处输入图像说明”

You can use the list extend method. It shows to be the fastest:

flat_list = []
for sublist in l:
    flat_list.extend(sublist)

Performance:

import functools
import itertools
import numpy
import operator
import perfplot


def functools_reduce_iconcat(a):
    return functools.reduce(operator.iconcat, a, [])


def itertools_chain(a):
    return list(itertools.chain.from_iterable(a))


def numpy_flat(a):
    return list(numpy.array(a).flat)


def extend(a):
    n = []

    list(map(n.extend, a))

    return n


perfplot.show(
    setup = lambda n: [list(range(10))] * n,
    kernels = [
        functools_reduce_iconcat, extend, itertools_chain, numpy_flat
        ],
    n_range = [2**k for k in range(16)],
    xlabel = 'num lists',
    )

Output:

Enter image description here

青丝拂面 2025-01-28 06:58:38

有几个答案,具有与下面相同的递归插入方案的答案,但是没有一个使用尝试,这使得解决方案更健壮, pythonic

def flatten(itr):
    for x in itr:
        try:
            yield from flatten(x)
        except TypeError:
            yield x

用法:这是一个生成器,通常您想将其包装在可观的构建器中在循环的中。

该解决方案的优点是:

  • 使用任何类型的峰值(甚至将来!)
  • 使用嵌套的任何组合和深度
  • ,如果最高级别包含裸露的项目,则
  • 不得不
  • 快速有效(您可以将嵌套的嵌套iTobles弄平,而不会部分地弄平,而不会浪费浪费在您不需要的剩余部分上的时间)
  • 多才多艺(您可以使用它来构建您选择的或循环中的一个值)

nb:由于 all aterables被扁平,因此将字符串分解为序列单个字符。如果您不喜欢/想要这样的行为,则可以使用以下版本,这些版本从字符串和字节(例如字符串和字节)中过滤出来:

def flatten(itr):
    if type(itr) in (str,bytes):
        yield itr
    else:
        for x in itr:
            try:
                yield from flatten(x)
            except TypeError:
                yield x

There are several answers with the same recursive appending scheme as below, but none makes use of try, which makes the solution more robust and Pythonic.

def flatten(itr):
    for x in itr:
        try:
            yield from flatten(x)
        except TypeError:
            yield x

Usage: this is a generator, and you typically want to enclose it in an iterable builder like list() or tuple() or use it in a for loop.

Advantages of this solution are:

  • works with any kind of iterable (even future ones!)
  • works with any combination and deepness of nesting
  • works also if top level contains bare items
  • no dependencies
  • fast and efficient (you can flatten the nested iterable partially, without wasting time on the remaining part you don't need)
  • versatile (you can use it to build an iterable of your choice or in a loop)

N.B.: Since all iterables are flattened, strings are decomposed into sequences of single characters. If you don't like/want such behavior, you can use the following version which filters out from flattening iterables like strings and bytes:

def flatten(itr):
    if type(itr) in (str,bytes):
        yield itr
    else:
        for x in itr:
            try:
                yield from flatten(x)
            except TypeError:
                yield x
森林迷了鹿 2025-01-28 06:58:38

注意:以下适用于Python 3.3+,因为它使用 fard_from 六个也是第三方软件包,尽管它是稳定的。或者,您可以使用 sys.version


对于 obj = [[1,2,],[3,4],[5,6]] ,这里的所有解决方案都很好,包括列表理解和 itertools .chain.from_iterable

但是,请考虑以下更复杂的情况:

>>> obj = [[1, 2, 3], [4, 5], 6, 'abc', [7], [8, [9, 10]]]

这里有几个问题:

  • 一个元素, 6 ,只是标量;这是不可能的,因此以上路线将在这里失败。
  • 一个元素,'abc'在技术上迭代的(所有 str s is)。但是,在两行之间读取一点,您不想将其视为这样 - 您想将其视为单个元素。
  • 最终元素, [8,[9,10]] 本身就是一个嵌套的迭代性。基本列表理解和链。from_iterable仅提取“ 1级别”。

您可以按照以下方式进行纠正:

>>> from collections import Iterable
>>> from six import string_types

>>> def flatten(obj):
...     for i in obj:
...         if isinstance(i, Iterable) and not isinstance(i, string_types):
...             yield from flatten(i)
...         else:
...             yield i


>>> list(flatten(obj))
[1, 2, 3, 4, 5, 6, 'abc', 7, 8, 9, 10]

在这里,您检查子元素(1)是否可以使用 iToble ,来自 itertools 的ABC,但也希望确保(2)元素是 not> not “类似字符串”。

Note: Below applies to Python 3.3+ because it uses yield_from. six is also a third-party package, though it is stable. Alternately, you could use sys.version.


In the case of obj = [[1, 2,], [3, 4], [5, 6]], all of the solutions here are good, including list comprehension and itertools.chain.from_iterable.

However, consider this slightly more complex case:

>>> obj = [[1, 2, 3], [4, 5], 6, 'abc', [7], [8, [9, 10]]]

There are several problems here:

  • One element, 6, is just a scalar; it's not iterable, so the above routes will fail here.
  • One element, 'abc', is technically iterable (all strs are). However, reading between the lines a bit, you don't want to treat it as such--you want to treat it as a single element.
  • The final element, [8, [9, 10]] is itself a nested iterable. Basic list comprehension and chain.from_iterable only extract "1 level down."

You can remedy this as follows:

>>> from collections import Iterable
>>> from six import string_types

>>> def flatten(obj):
...     for i in obj:
...         if isinstance(i, Iterable) and not isinstance(i, string_types):
...             yield from flatten(i)
...         else:
...             yield i


>>> list(flatten(obj))
[1, 2, 3, 4, 5, 6, 'abc', 7, 8, 9, 10]

Here, you check that the sub-element (1) is iterable with Iterable, an ABC from itertools, but also want to ensure that (2) the element is not "string-like."

香草可樂 2025-01-28 06:58:38

如果您愿意放弃少量的速度以使外观更清洁,则可以使用 numpy.concatenate()。tolist() numpy.concatenate()。ravel()。 .tolist()

import numpy

l = [[1, 2, 3], [4, 5, 6], [7], [8, 9]] * 99

%timeit numpy.concatenate(l).ravel().tolist()
1000 loops, best of 3: 313 µs per loop

%timeit numpy.concatenate(l).tolist()
1000 loops, best of 3: 312 µs per loop

%timeit [item for sublist in l for item in sublist]
1000 loops, best of 3: 31.5 µs per loop

您可以在文档中找到更多信息, numpy.concatenate

If you are willing to give up a tiny amount of speed for a cleaner look, then you could use numpy.concatenate().tolist() or numpy.concatenate().ravel().tolist():

import numpy

l = [[1, 2, 3], [4, 5, 6], [7], [8, 9]] * 99

%timeit numpy.concatenate(l).ravel().tolist()
1000 loops, best of 3: 313 µs per loop

%timeit numpy.concatenate(l).tolist()
1000 loops, best of 3: 312 µs per loop

%timeit [item for sublist in l for item in sublist]
1000 loops, best of 3: 31.5 µs per loop

You can find out more here in the documentation, numpy.concatenate and numpy.ravel.

涫野音 2025-01-28 06:58:38
def flatten(alist):
    if alist == []:
        return []
    elif type(alist) is not list:
        return [alist]
    else:
        return flatten(alist[0]) + flatten(alist[1:])
def flatten(alist):
    if alist == []:
        return []
    elif type(alist) is not list:
        return [alist]
    else:
        return flatten(alist[0]) + flatten(alist[1:])
只为一人 2025-01-28 06:58:38

我想要一个可以处理多个嵌套的解决方案( [[1],[[[2]],[3]]],[1,2,3] ),但也会不要递归(我有很大的递归水平,并且有递归错误。

这就是我想到的:

def _flatten(l) -> Iterator[Any]:
    stack = l.copy()
    while stack:
        item = stack.pop()
        if isinstance(item, list):
            stack.extend(item)
        else:
            yield item


def flatten(l) -> Iterator[Any]:
    return reversed(list(_flatten(l)))

和测试:

@pytest.mark.parametrize('input_list, expected_output', [
    ([1, 2, 3], [1, 2, 3]),
    ([[1], 2, 3], [1, 2, 3]),
    ([[1], [2], 3], [1, 2, 3]),
    ([[1], [2], [3]], [1, 2, 3]),
    ([[1], [[2]], [3]], [1, 2, 3]),
    ([[1], [[[2]], [3]]], [1, 2, 3]),
])
def test_flatten(input_list, expected_output):
    assert list(flatten(input_list)) == expected_output

I wanted a solution which can deal with multiple nesting ([[1], [[[2]], [3]]], [1, 2, 3] for example), but would also not be recursive (I had a big level of recursion and I got a recursion error.

This is what I came up with:

def _flatten(l) -> Iterator[Any]:
    stack = l.copy()
    while stack:
        item = stack.pop()
        if isinstance(item, list):
            stack.extend(item)
        else:
            yield item


def flatten(l) -> Iterator[Any]:
    return reversed(list(_flatten(l)))

and tests:

@pytest.mark.parametrize('input_list, expected_output', [
    ([1, 2, 3], [1, 2, 3]),
    ([[1], 2, 3], [1, 2, 3]),
    ([[1], [2], 3], [1, 2, 3]),
    ([[1], [2], [3]], [1, 2, 3]),
    ([[1], [[2]], [3]], [1, 2, 3]),
    ([[1], [[[2]], [3]]], [1, 2, 3]),
])
def test_flatten(input_list, expected_output):
    assert list(flatten(input_list)) == expected_output
扮仙女 2025-01-28 06:58:38

这可能不是最有效的方法,但我认为放置了一个单线(实际上是两线线)。这两个版本都将在任意层次结构列表上使用,并利用语言功能(Python&nbsp; 3.5)和递归。

def make_list_flat (l):
    flist = []
    flist.extend ([l]) if (type (l) is not list) else [flist.extend (make_list_flat (e)) for e in l]
    return flist

a = [[1, 2], [[[[3, 4, 5], 6]]], 7, [8, [9, [10, 11], 12, [13, 14, [15, [[16, 17], 18]]]]]]
flist = make_list_flat(a)
print (flist)

输出是以

[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18]

一种深度的初步方式起作用。递归降低直到找到非上列元素,然后扩展局部变量 flist ,然后将其滚动给父。每当返回 flist 时,它将扩展到列表理解中的父 flist 。因此,在根本上,返回平面列表。

以上一个创建了几个本地列表并返回用于扩展父列表的这些列表。我认为这可能是创建Gloabl flist ,如下所示。

a = [[1, 2], [[[[3, 4, 5], 6]]], 7, [8, [9, [10, 11], 12, [13, 14, [15, [[16, 17], 18]]]]]]
flist = []
def make_list_flat (l):
    flist.extend ([l]) if (type (l) is not list) else [make_list_flat (e) for e in l]

make_list_flat(a)
print (flist)

输出又是又一次。

[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18]

尽管我目前不确定效率,但

This may not be the most efficient way, but I thought to put a one-liner (actually a two-liner). Both versions will work on arbitrary hierarchy nested lists, and exploits language features (Python 3.5) and recursion.

def make_list_flat (l):
    flist = []
    flist.extend ([l]) if (type (l) is not list) else [flist.extend (make_list_flat (e)) for e in l]
    return flist

a = [[1, 2], [[[[3, 4, 5], 6]]], 7, [8, [9, [10, 11], 12, [13, 14, [15, [[16, 17], 18]]]]]]
flist = make_list_flat(a)
print (flist)

The output is

[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18]

This works in a depth first manner. The recursion goes down until it finds a non-list element, then extends the local variable flist and then rolls back it to the parent. Whenever flist is returned, it is extended to the parent's flist in the list comprehension. Therefore, at the root, a flat list is returned.

The above one creates several local lists and returns them which are used to extend the parent's list. I think the way around for this may be creating a gloabl flist, like below.

a = [[1, 2], [[[[3, 4, 5], 6]]], 7, [8, [9, [10, 11], 12, [13, 14, [15, [[16, 17], 18]]]]]]
flist = []
def make_list_flat (l):
    flist.extend ([l]) if (type (l) is not list) else [make_list_flat (e) for e in l]

make_list_flat(a)
print (flist)

The output is again

[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18]

Although I am not sure at this time about the efficiency.

青朷 2025-01-28 06:58:38

如果您想毫不掩饰所有内容并保留不同的元素列表,则也可以使用它。

list_of_lists = [[1,2], [2,3], [3,4]]
list(set.union(*[set(s) for s in list_of_lists]))

If you want to unnest everything and keep a distinct list of elements, you could use this as well.

list_of_lists = [[1,2], [2,3], [3,4]]
list(set.union(*[set(s) for s in list_of_lists]))
2025-01-28 06:58:38

这是我在其他答案中没有看到的一种方法。它支持任何层次的嵌套,迭代和无库的工作:

mylist = [[1,2,4,5],[[0,8,9],5,7],[3,11,[44,45,46],25]]

for i,_ in enumerate(mylist):          # indexes, including extended positions
    while isinstance(mylist[i],list):  # drill down/extend current position
        mylist[i:i+1] = mylist[i]      # as long as item is a list

print(mylist)
[1, 2, 4, 5, 0, 8, 9, 5, 7, 3, 11, 44, 45, 46, 25]

Here's an approach I didn't see in the other answers. It supports any level of nesting, works iteratively and without libraries:

mylist = [[1,2,4,5],[[0,8,9],5,7],[3,11,[44,45,46],25]]

for i,_ in enumerate(mylist):          # indexes, including extended positions
    while isinstance(mylist[i],list):  # drill down/extend current position
        mylist[i:i+1] = mylist[i]      # as long as item is a list

print(mylist)
[1, 2, 4, 5, 0, 8, 9, 5, 7, 3, 11, 44, 45, 46, 25]
烂人 2025-01-28 06:58:38

我建议使用具有产量语句的发电机和的产量。

这是一个例子:

from collections.abc import Iterable

def flatten(items, ignore_types=(bytes, str)):
    """
       Flatten all of the nested lists to the one. Ignoring flatting of iterable types str and bytes by default.
    """
    for x in items:
        if isinstance(x, Iterable) and not isinstance(x, ignore_types):
            yield from flatten(x)
        else:
            yield x

values = [7, [4, 3, 5, [7, 3], (3, 4), ('A', {'B', 'C'})]]

for v in flatten(values):
    print(v)

I would suggest using generators with a yield statement and yield from.

Here's an example:

from collections.abc import Iterable

def flatten(items, ignore_types=(bytes, str)):
    """
       Flatten all of the nested lists to the one. Ignoring flatting of iterable types str and bytes by default.
    """
    for x in items:
        if isinstance(x, Iterable) and not isinstance(x, ignore_types):
            yield from flatten(x)
        else:
            yield x

values = [7, [4, 3, 5, [7, 3], (3, 4), ('A', {'B', 'C'})]]

for v in flatten(values):
    print(v)
情域 2025-01-28 06:58:38

另一种适用于异性和同质整数列表的不寻常方法:

from typing import List


def flatten(l: list) -> List[int]:
    """Flatten an arbitrary deep nested list of lists of integers.

    Examples:
        >>> flatten([1, 2, [1, [10]]])
        [1, 2, 1, 10]

    Args:
        l: Union[l, Union[int, List[int]]

    Returns:
        Flatted list of integer
    """
    return [int(i.strip('[ ]')) for i in str(l).split(',')]

Another unusual approach that works for hetero- and homogeneous lists of integers:

from typing import List


def flatten(l: list) -> List[int]:
    """Flatten an arbitrary deep nested list of lists of integers.

    Examples:
        >>> flatten([1, 2, [1, [10]]])
        [1, 2, 1, 10]

    Args:
        l: Union[l, Union[int, List[int]]

    Returns:
        Flatted list of integer
    """
    return [int(i.strip('[ ]')) for i in str(l).split(',')]
你与清晨阳光 2025-01-28 06:58:38

一个非恢复功能,可以使任何深度列表的列表更平坦:

def flatten_list(list1):
    out = []
    inside = list1
    while inside:
        x = inside.pop(0)
        if isinstance(x, list):
            inside[0:0] = x
        else:
            out.append(x)
    return out

l = [[[1,2],3,[4,[[5,6],7],[8]]],[9,10,11]]
flatten_list(l)
# [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]

A non-recursive function to flatten lists of lists of any depth:

def flatten_list(list1):
    out = []
    inside = list1
    while inside:
        x = inside.pop(0)
        if isinstance(x, list):
            inside[0:0] = x
        else:
            out.append(x)
    return out

l = [[[1,2],3,[4,[[5,6],7],[8]]],[9,10,11]]
flatten_list(l)
# [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]
梦归所梦 2025-01-28 06:58:38

不是一个单线,但是在这里看到所有答案,我想这个长列表错过了一些模式匹配,所以:)

这两种方法可能不是有效的,但是无论如何,它很容易阅读(至少对我来说;也许我被功能编程所宠坏了):

def flat(x):
    match x:
        case []:
            return []
        case [[*sublist], *r]:
            return [*sublist, *flat(r)]

第二版认为列表的列表列表...嵌套是什么:

def flat(x):
    match x:
        case []:
            return []
        case [[*sublist], *r]:
            return [*flat(sublist), *flat(r)]
        case [h, *r]:
            return [h, *flat(r)]

Not a one-liner, but seeing all the answers here, I guess this long list missed some pattern matching, so here it is :)

The two methods are probably not efficient, but anyway, it's easy to read (to me at least; perhaps I'm spoiled by functional programming):

def flat(x):
    match x:
        case []:
            return []
        case [[*sublist], *r]:
            return [*sublist, *flat(r)]

The second version considers lists of lists of lists... whatever the nesting:

def flat(x):
    match x:
        case []:
            return []
        case [[*sublist], *r]:
            return [*flat(sublist), *flat(r)]
        case [h, *r]:
            return [h, *flat(r)]
微暖i 2025-01-28 06:58:38

如果您有一个numpy数组 a

a = np.array([[1,2], [3,4]])
a.flatten('C')

生产:

[1, 2, 3, 4]

np.flatten 还接受其他参数:

  • c
  • f f
  • < <代码> a
  • k

有关参数的更多详细信息在这里

If you have a numpy array a:

a = np.array([[1,2], [3,4]])
a.flatten('C')

produces:

[1, 2, 3, 4]

np.flatten also accepts other parameters:

  • C:
  • F
  • A
  • K

More details about parameters are available here.

余生共白头 2025-01-28 06:58:38

如果我想在以前的出色答案中添加一些东西,这是我的递归扁平函数,它不仅可以弄平嵌套列表,还可以弄平任何给定的容器或任何可以抛出项目的任何对象。这也适用于任何嵌套深度,它是一个懒惰的迭代器,可根据要求产生项目:

def flatten(iterable):
    # These types won't considered a sequence or generally a container
    exclude = str, bytes

    for i in iterable:
        try:
            if isinstance(i, exclude):
                raise TypeError
            iter(i)
        except TypeError:
            yield i
        else:
            yield from flatten(i)

这样,您可以排除不想被扁平的类型,例如 str 或其他什么。

这个想法是,如果对象可以传递 iter()准备就可以产生项目。因此,峰值可以将发电机表达式作为项目。

有人可以争论:当OP不要求它时,为什么要写这件事?好,你是对的。我只是觉得这可能会帮助某人(就像我自己一样)。

测试用例:

lst1 = [1, {3}, (1, 6), [[3, 8]], [[[5]]], 9, ((((2,),),),)]
lst2 = ['3', B'A', [[[(i ** 2 for i in range(3))]]], range(3)]

print(list(flatten(lst1)))
print(list(flatten(lst2)))

输出:

[1, 3, 1, 6, 3, 8, 5, 9, 2]
['3', b'A', 0, 1, 4, 0, 1, 2]

If I want to add something to the great previous answers, here is my recursive flatten function which can flatten not only nested lists, but also any given container or any generally any object which can throw out items. This does also work for any depth of nesting and it is a lazy iterator which yields the items as requested:

def flatten(iterable):
    # These types won't considered a sequence or generally a container
    exclude = str, bytes

    for i in iterable:
        try:
            if isinstance(i, exclude):
                raise TypeError
            iter(i)
        except TypeError:
            yield i
        else:
            yield from flatten(i)

This way, you can exclude types you don't want to be flattened, like str or what else.

The idea is if an object can pass the iter() it's ready to yield items. So the iterable can have even generator expressions as an item.

Someone could argue: Why did you write this that generic when the OP didn't ask for it? OK, you're right. I just felt like this might help someone (like it did for myself).

Test cases:

lst1 = [1, {3}, (1, 6), [[3, 8]], [[[5]]], 9, ((((2,),),),)]
lst2 = ['3', B'A', [[[(i ** 2 for i in range(3))]]], range(3)]

print(list(flatten(lst1)))
print(list(flatten(lst2)))

Output:

[1, 3, 1, 6, 3, 8, 5, 9, 2]
['3', b'A', 0, 1, 4, 0, 1, 2]
猫卆 2025-01-28 06:58:38

这使用 parsel.utils.flatten ,这在变平多个列表嵌套方面非常好。我发现避免开销 numpy

我将在此处使用数字来简单起见,但是我主要将其与字符串一起使用,这是为了我的目的,它很快就可以使用(每个嵌套的列表,每个元素约40个元素)。

nested_list = [[1, 2, [3, 4]], [5, [6, [7, 8]]]]
flattened_list = parsel.utils.flatten(nested_list)
print(flattened_list)
-> [1, 2, 3, 4, 5, 6, 7, 8]

This uses parsel.utils.flatten which is great when it comes to flattening multiple levels of list nesting. I found it useful to avoid overhead of NumPy.

I'll use numbers here for the purpose of simplicity, but but I predominantly used it with strings, which worked pretty fast for my purposes (200 nested lists with each about 40 elements).

nested_list = [[1, 2, [3, 4]], [5, [6, [7, 8]]]]
flattened_list = parsel.utils.flatten(nested_list)
print(flattened_list)
-> [1, 2, 3, 4, 5, 6, 7, 8]
眼泪都笑了 2025-01-28 06:58:38

我喜欢添加一个高性能的生成器解决方案,该解决方案可以使的任何深度不(只有二维列表)添加嵌套列表(或任何类型的峰值):

from itertools import chain

def flatten_deep_generator(iterable):
    iterator = iter(iterable)
    try:
        while 1: # StopIteration will break the loop
            item = next(iterator)
            # Check if item contains sub-items
            if not hasattr(item,'__trunc__'):
                iterator = chain(iter(item), iterator)
            else:
                yield item
    except StopIteration:
        pass

根据您的需求,生成器具有巨大的优势列表。例如,如果要添加 filter()之后功能。最终的列表应仅在构造完整发电机含量之后的结尾进行实例。通过这种过滤,您可以避免对项目进行多次迭代。

备注:与其他提出的发电机解决方案相比,这是一种迭代而不是递归解决方案,可以避免在深嵌套的迭代物体的情况下避免递归词。

I like to add a high performant generator solution which can fatten nested lists (or any kind of iterable) of any depth not (only two-dimensional-lists):

from itertools import chain

def flatten_deep_generator(iterable):
    iterator = iter(iterable)
    try:
        while 1: # StopIteration will break the loop
            item = next(iterator)
            # Check if item contains sub-items
            if not hasattr(item,'__trunc__'):
                iterator = chain(iter(item), iterator)
            else:
                yield item
    except StopIteration:
        pass

Depending on your needs a generators have huge advantages over lists. E.g. If you want add filter() functions afterwards. The resulting list should be instanced only at the end after you have constructed the full generator incl. the filtering by this you avoid multiple iterations over the items.

Remark: Compared to the other proposed generator solution this is an iterative and not a recursive solution which avoids RecursionErrors in case of deep nested iterables.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文