将两个不均匀的列表与填充要求混合

时间:2014-07-05 04:35:33

标签: python

我在Python中混合了两个列表,虽然我知道有类似的问题,但我需要以某种方式处理它。

我有两个列表,它们的长度可能相同,也可能不同。我需要交织两者并使用填充物作为较短的列表,但填充物必须在较短列表中的任何值之前。

这就是我目前所拥有的:

def mix(a, b):
    fill='spam'
    if len(a) > len(b):
        d = len(a) - len(b)
        while d:
            b.insert(0, fill)
            d-=1
    if len(a) < len(b):
        d = len(b) - len(a)
        while d:
            a.insert(0, fill)
            d-=1

    n = zip(a, b)
    mixed = [item for sub in n for item in sub]
    return mixed

示例:

>>> mix([1, 2 ,3], ['A', 'B', 'C', 'D', 'E', 'F'])
['spam', 'A', 'spam', 'B', 'spam', 'C', 1, 'D', 2, 'E', 3, 'F']

所以代码可以工作,但它似乎不是一个好方法。还有更好的方法吗?

3 个答案:

答案 0 :(得分:5)

如果要将一个元素粘贴到列表中的两个元素上,可以利用切片。

这是一个可能的实现:

In [39]: l1 = [1,2,3]
    ...: l2 = ['A', 'B', 'C', 'D', 'E', 'F']
    ...: fill = 'spam'
    ...: 

In [40]: l = 2 * max(len(l1), len(l2))  # final length
    ...: mixed = [fill] * l  # result is initialized with the filler
    ...: mixed[l-2*len(l1)::2] = l1  # paste l1
    ...: mixed[l-2*len(l2)+1::2] = l2  # paste l2
    ...: mixed
    ...: 
Out[40]: ['spam', 'A', 'spam', 'B', 'spam', 'C', 1, 'D', 2, 'E', 3, 'F']

答案 1 :(得分:1)

import itertools


def mix(a, b):
    diff = len(a) - len(b)
    fill = 'spam'
    if diff > 0:
        b = [fill] * diff + b
    elif diff < 0:
        a = [fill] * abs(diff) + a
    return list(itertools.chain(*zip(a, b)))

您可能听说Python包含电池,即它可能具有内置的实用程序/功能,这有助于使程序更简单,更易读。上述功能与原始功能有两个主要区别:

  • 使用列表乘法和加法:在Python中,列表可以添加另一个列表,并且可以乘以整数。

例如:

>>> [1, 2, 3] + ['a', 'b']
>>> [1, 2, 3, 'a', 'b']


>>> [1] * 3
>>> [1, 1, 1]
>>> [1, 2] * 2
>>> [1, 2, 1, 2]
  • itertools.chain function :这个函数只是将作为参数提供给它的迭代器/迭代的列表(不是python列表)链接到单个迭代器中。

例如:

>>> list(itertools.chain([1, 2], [3, 4], [5, 6]))
>>> [1, 2, 3, 4, 5, 6]

答案 2 :(得分:0)

不能说这是一种更好的方法,但它确实利用了Python标准库中的工具(itertools.izip_longest),该工具旨在通过填充默认元素来处理压缩不等长度列表

import itertools

def mix(a, b):
    a_rev = reversed(a)
    b_rev = reversed(b)
    if len(a) > len(b):
        temp = itertools.izip_longest(a_rev, b_rev, fillvalue='spam')
    elif len(b) > len(a):
        temp = itertools.izip_longest(b_rev, a_rev, fillvalue='spam')      
    sequence = list()
    for item in temp:
    sequence.extend(item)
    return sequence

o = mix([1, 2 ,3], ['A', 'B', 'C', 'D', 'E', 'F'])
o.reverse()
print(o)