2

我目前正在学习python中列表推导的概念。但是,当我迭代的列表包含相同或不同长度的子列表时,我会遇到很大的问题。例如,我想将代码union_set()转换为单行理解:

def union_set(L):
    S_union = set()

    for i in range(len(L)):
        S_union.update(set(L[i]))

    return S_union


L1 = [1, 2, 3]
L2 = [4, 5, 6]
L3 = [7, 8, 9]

L = [L1, L2, L3]
print(L)

print(union_set(L))

我很确定这应该是可能的(也许通过“以某种方式”解压缩子列表的内容(?)),但我害怕我在这里遗漏了一些东西。任何人都可以帮忙吗?

4

4 回答 4

4

使用列表理解,您可以执行以下操作:

>>> L1 = [1, 2, 3]
>>> L2 = [4, 5, 6]
>>> L3 = [7, 8, 9]
>>> L = [L1, L2, L3]
>>> s=set([x for y in L for x in y])
>>> s
set([1, 2, 3, 4, 5, 6, 7, 8, 9])

y 迭代子列表,而 x 迭代 y 中的项目。

于 2013-07-08T10:58:12.333 回答
3

使用一个空的set.union它:

L1 = [1, 2, 3]
L2 = [4, 5, 6]
L3 = [7, 8, 9]

print set().union(L1, L2, L3)

在您的代码中用作:

L = [L1, L2, L3]

def union_set(L):
    return set().union(*L)
于 2013-07-08T10:59:09.023 回答
2

使用 * 进行拆包并将拆包的物品传递给set.union

>>> L = [L1, L2, L3]
>>> set.union(*(set(x) for x in L))
set([1, 2, 3, 4, 5, 6, 7, 8, 9])

使用的高效版本itertools

>>> from itertools import islice
>>> set.union(set(L[0]),*islice(L,1,None))
set([1, 2, 3, 4, 5, 6, 7, 8, 9])

>>> from itertools import chain
>>> set(chain.from_iterable(L))
set([1, 2, 3, 4, 5, 6, 7, 8, 9])

时间比较:

>>> L = [L1, L2, L3]*10**5

>>> %timeit set.union(*(set(x) for x in L))
1 loops, best of 3: 416 ms per loop

>>> %timeit set(chain.from_iterable(L))               # winner
1 loops, best of 3: 69.4 ms per loop

>>> %timeit set.union(set(L[0]),*islice(L,1,None))
1 loops, best of 3: 78.6 ms per loop

>>> %timeit set().union(*L)
1 loops, best of 3: 105 ms per loop

>>> %timeit set(chain(*L))
1 loops, best of 3: 79.2 ms per loop

>>> %timeit s=set([x for y in L for x in y])
1 loops, best of 3: 151 ms per loop
于 2013-07-08T10:55:52.970 回答
1

你可以这样itertools.chain使用

>>> L1 = [1, 2, 3]
>>> L2 = [4, 5, 6]
>>> L3 = [7, 8, 9]
>>> L = [L1,L2,L3]

>>> set(itertools.chain(*L))
set([1, 2, 3, 4, 5, 6, 7, 8, 9])

*解包列表,并chain从子列表中创建一个列表。

于 2013-07-08T10:59:23.113 回答