46

我有两个清单

a = [1,2,3]
b = [9,10]

我想将这两个列表合并(压缩)到一个列表中c,这样

c = [(1,9), (2,10), (3, )]

Python的标准库中是否有任何功能可以做到这一点?

4

4 回答 4

64

通常,您itertools.zip_longest用于此:

>>> import itertools
>>> a = [1, 2, 3]
>>> b = [9, 10]
>>> for i in itertools.zip_longest(a, b): print(i)
... 
(1, 9)
(2, 10)
(3, None)

但是用 s (或您作为参数传递的任何值)zip_longest填充较短的可迭代对象。如果这不是您想要的,那么您可以使用理解来过滤掉s:Nonefillvalue=None

>>> for i in (tuple(p for p in pair if p is not None) 
...           for pair in itertools.zip_longest(a, b)):
...     print(i)
... 
(1, 9)
(2, 10)
(3,)

但请注意,如果任何一个可迭代对象都有None值,这也会将它们过滤掉。如果您不希望这样,请定义您自己的对象fillvalue=并对其进行过滤,而不是None

sentinel = object()

def zip_longest_no_fill(a, b):
    for i in itertools.zip_longest(a, b, fillvalue=sentinel):
        yield tuple(x for x in i if x is not sentinel)

list(zip_longest_no_fill(a, b))  # [(1, 9), (2, 10), (3,)]

于 2012-07-03T20:53:23.903 回答
9

另一种方法是map

a = [1, 2, 3]
b = [9, 10]
c = map(None, a, b)

尽管那也将包含(3, None)而不是(3,). 为此,这里有一条有趣的线路:

c = (tuple(y for y in x if y is not None) for x in map(None, a, b))
于 2012-07-03T20:58:37.660 回答
3

编写显式 Python 来执行所需的操作并不难:

def izip_short(a, b):
    ia = iter(a)
    ib = iter(b)
    for x in ia:
        try:
            y = next(ib)
            yield (x, y)
        except StopIteration:
            yield (x,)
            break
    for x in ia:
        yield (x,)
    for y in ib:
        yield (None, y)

a = [1, 2, 3]
b = [9, 10]
list(izip_short(a, b))
list(izip_short(b, a))

我不确定你想如何处理b比序列长的a序列,所以在这种情况下,我只是None将元组中的第一个值填入 a 中。

为每个序列获取一个显式迭代器。将a迭代器作为for循环运行,同时手动使用next(ib)b序列中获取下一个值。如果我们StopIterationb序列上得到 a,我们打破循环,然后for x in ia:得到a序列的其余部分;之后for y in ib:什么都不做,因为那个迭代器已经用完了。或者,如果第一个for x in ia:循环耗尽了a迭代器,那么第二个循环for x in ia:什么也不做,但b序列中可能会留下一些值,然后for y in ib:循环收集它们。

于 2012-07-03T21:26:20.317 回答
1

单线:

c = zip(a, b) + [(x,) for x in a[len(b):]] + [(x,) for x in b[len(a):]]

如果你想重用这个:

def mergeUsNicely(a, b):
    def tupleMe(val):
        return (val,)
    return zip(a, b) + map(tupleMe, a[len(b):]) + map(tupleMe, b[len(a):])
于 2014-06-23T07:51:17.260 回答