内部列表或整数的连接

时间:2013-06-21 19:54:36

标签: python numpy concatenation flatten

我觉得我错过了一些明显的东西,但它是......我想从以下地方出发:

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-loop很好,但感觉应该有更优雅的方式来做这个...尝试用numpy做这个似乎更复杂,因为不好的数组不容易处理..所以你不能(例如):

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

提前致谢。

更新

这是我对@ T.J和@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

UPDATE2:

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

3 个答案:

答案 0 :(得分: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

答案 1 :(得分: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

答案 2 :(得分: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), [])

您应该提供总和[]的初始值,以便从

开始求和

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

但是人们应该注意字符串也是可迭代的。并且如果在上层将有字符串,它将被激活到字符中。