Python列表转置和填充

Python列表转置和填充,python,list,fill,transpose,Python,List,Fill,Transpose,我有一个列表列表,每个内部列表的长度为1或n(假设n>1) 我想转换列表,但不是截断较长的列表(如使用zip)或用None填充较短的列表,而是用它们自己的单数值填充较短的列表。换句话说,我想得到: >>> [(1, 47, 3, 12), (1, 17, 3, 5), (1, 2, 3, 75), (1, 3, 3, 33)] 我可以通过几次迭代来实现这一点: >>> maxlist = len(max(*uneven, key=len)) >>

我有一个列表列表,每个内部列表的长度为1或n(假设n>1)

我想转换列表,但不是截断较长的列表(如使用
zip
)或用
None
填充较短的列表,而是用它们自己的单数值填充较短的列表。换句话说,我想得到:

>>> [(1, 47, 3, 12), (1, 17, 3, 5), (1, 2, 3, 75), (1, 3, 3, 33)]
我可以通过几次迭代来实现这一点:

>>> maxlist = len(max(*uneven, key=len))
>>> maxlist
4
>>> from itertools import repeat
>>> uneven2 = [x if len(x) == maxlist else repeat(x[0], maxlist) for x in uneven]
>>> uneven2
[[1, 1, 1, 1], [47, 17, 2, 3], [3, 3, 3, 3], [12, 5, 75, 33]]
>>> zip(*uneven2)
[(1, 47, 3, 12), (1, 17, 3, 5), (1, 2, 3, 75), (1, 3, 3, 33)]

但有更好的方法吗?我真的需要事先知道
maxlist
才能完成此任务吗?

您可以永远重复一个元素列表:

uneven = [[1], [47, 17, 2, 3], [3], [12, 5, 75, 33]]

from itertools import repeat

print zip(*(repeat(*x) if len(x)==1 else x for x in uneven))
您可以改为使用:


这意味着你不需要提前知道
maxlist

我真的很喜欢@chris morgan模拟
itertools.izip_longest
的想法,所以当我最终得到灵感时,我写了一个
izip_cycle
函数

def izip_cycle(*iterables, **kwargs):
    """Make an iterator that aggregates elements from each of the iterables.
    If the iterables are of uneven length, missing values are filled-in by cycling the shorter iterables.
    If an iterable is empty, missing values are fillvalue or None if not specified.
    Iteration continues until the longest iterable is exhausted.
    """
    fillvalue = kwargs.get('fillvalue')
    counter = [len(iterables)]
    def cyclemost(iterable):
        """Cycle the given iterable like itertools.cycle, unless the counter has run out."""
        itb = iter(iterable)
        saved = []
        try:
            while True:
                element = itb.next()
                yield element
                saved.append(element)
        except StopIteration:
            counter[0] -= 1
            if counter[0] > 0:
                saved = saved or [fillvalue]
                while saved:
                    for element in saved:
                        yield element
    iterators = [cyclemost(iterable) for iterable in iterables]
    while iterators:
        yield tuple([next(iterator) for iterator in iterators])

print list(izip_cycle([], range(3), range(6), fillvalue='@'))

您可以模拟
itertools.izip_longest
,只需在序列用尽时使用序列的最后一个值,而不是
fillvalue
。@ChrisMorgan是对的,您看到了这个链接,可能还可以从那里使用一些其他函数。这非常有用,因为n=1内部列表是生成的。现在我已经进行了重构,所以列表是
[重复(1),[47,17,2,3],重复(3),[12,5,75,33]]
,我可以只做
zip(*不均匀)
>>> from itertools import cycle
>>> uneven3 = [x if len(x) != 1 else cycle(x) for x in uneven]
>>> zip(*uneven3)
[(1, 47, 3, 12), (1, 17, 3, 5), (1, 2, 3, 75), (1, 3, 3, 33)]
def izip_cycle(*iterables, **kwargs):
    """Make an iterator that aggregates elements from each of the iterables.
    If the iterables are of uneven length, missing values are filled-in by cycling the shorter iterables.
    If an iterable is empty, missing values are fillvalue or None if not specified.
    Iteration continues until the longest iterable is exhausted.
    """
    fillvalue = kwargs.get('fillvalue')
    counter = [len(iterables)]
    def cyclemost(iterable):
        """Cycle the given iterable like itertools.cycle, unless the counter has run out."""
        itb = iter(iterable)
        saved = []
        try:
            while True:
                element = itb.next()
                yield element
                saved.append(element)
        except StopIteration:
            counter[0] -= 1
            if counter[0] > 0:
                saved = saved or [fillvalue]
                while saved:
                    for element in saved:
                        yield element
    iterators = [cyclemost(iterable) for iterable in iterables]
    while iterators:
        yield tuple([next(iterator) for iterator in iterators])

print list(izip_cycle([], range(3), range(6), fillvalue='@'))