0

我觉得我错过了一些明显的东西,但它就是......我想从:

lst = [[0, 1, 3, 7, 8, 11, 12], [8, 0, 1, 2, 3, 14], 2]

至:

output = [0, 1, 3, 7, 8, 11, 12, 8, 0, 1, 2, 3, 14, 2]

我可以使用 for 循环来做到这一点,例如:

output = []
for l in lst:
    if hasattr(l, '__iter__'):
        output.extend(l)
    else:
        output.append(l)

也许 for 循环很好,但感觉应该有一种更优雅的方式来做到这一点......尝试用 numpy 来做这件事似乎更令人费解,因为不容易处理参差不齐的数组......所以你可以' t(例如):

output = np.asanyarray(lst).flatten().tolist()

提前致谢。

更新:

这是我对@TJ 和@Ashwini 提供的两种方法的比较——感谢两者!

In [5]: %paste
from itertools import chain
from collections import Iterable
lis = [[0, 1, 3, 7, 8, 11, 12], [8, 0, 1, 2, 3, 14], 2]
def solve(lis):
    for x in lis:
        if isinstance(x, Iterable) and not isinstance(x, basestring):
            yield x
        else:
            yield [x]

%timeit list(chain.from_iterable(solve(lis)))

%timeit [a for x in lis for a in (x if isinstance(x, Iterable) and not isinstance(x,basestring) else [x])]
## -- End pasted text --
100000 loops, best of 3: 10.1 us per loop
100000 loops, best of 3: 8.12 us per loop

更新2:

...
lis = lis *10**5
%timeit list(chain.from_iterable(solve(lis)))

%timeit [a for x in lis for a in (x if isinstance(x, Iterable) and not isinstance(x,basestring) else [x])]
## -- End pasted text --
1 loops, best of 3: 699 ms per loop
1 loops, best of 3: 698 ms per loop
4

3 回答 3

2

你可以itertools.chain这样使用:

>>> from itertools import chain
>>> from collections import Iterable
>>> lis = [[0, 1, 3, 7, 8, 11, 12], [8, 0, 1, 2, 3, 14], 2]
def solve(lis):
    for x in lis:
        if isinstance(x, Iterable) and not isinstance(x, basestring):
            yield x
        else:
            yield [x]
...             

>>> list(chain.from_iterable(solve(lis)))
[0, 1, 3, 7, 8, 11, 12, 8, 0, 1, 2, 3, 14, 2]

也适用于字符串:

>>> lis = [[0, 1, 3, 7, 8, 11, 12], [8, 0, 1, 2, 3, 14], "234"]
>>> list(chain.from_iterable(solve(lis)))
[0, 1, 3, 7, 8, 11, 12, 8, 0, 1, 2, 3, 14, '234']

时间比较:

>>> lis = lis *(10**4)
#modified version of FJ's answer that works for strings as well
>>> %timeit [a for x in lis for a in (x if isinstance(x, Iterable) and not isinstance(x,basestring) else [x])]
10 loops, best of 3: 110 ms per loop

>>> %timeit list(chain.from_iterable(solve(lis)))
1 loops, best of 3: 98.3 ms per loop
于 2013-06-21T19:56:24.190 回答
1

这是一个使用列表推导的非常简单的方法:

>>> data = [[0, 1, 3, 7, 8, 11, 12], [8, 0, 1, 2, 3, 14], 2]
>>> [a for x in data for a in (x if isinstance(x, list) else [x])]
[0, 1, 3, 7, 8, 11, 12, 8, 0, 1, 2, 3, 14, 2]

这是时序比较,看起来我的版本稍微快一些(请注意,我修改了我的代码以collections.Iterable确保比较公平):

In [9]: %timeit list(chain.from_iterable(solve(data)))
100000 loops, best of 3: 9.22 us per loop

In [10]: %timeit [a for x in data for a in (x if isinstance(x, Iterable) else [x])]
100000 loops, best of 3: 6.45 us per loop
于 2013-06-21T19:59:46.050 回答
0

您可以使用生成器使列表仅由可迭代对象组成

((i if isinstance(i,Iterable) else [i]) 

然后使用以下任何一种方法将它们连接到一个列表中:

你会尝试sum

from collections import Iterable
lis = [[0, 1, 3, 7, 8, 11, 12], [8, 0, 1, 2, 3, 14], 2]
sum(((i if isinstance(i,Iterable) else [i]) for i in lis), [])

您应该为 sum 提供初始值[]以开始总和

或者itertools.chain() 但在这种情况下,您应该将您的上级列表解压缩为一组列表

import itertools
lis = [[0, 1, 3, 7, 8, 11, 12], [8, 0, 1, 2, 3, 14], 2]
list(itertools.chain(*((i if isinstance(i,Iterable) else [i]) for i in lis)))

或者只是列出理解

[a for x in input for a in (x if isinstance(x, Iterable) else [x])]

但是应该注意字符串也是可迭代的。如果上层有字符串,它会变成字符。

于 2013-06-21T19:57:54.440 回答