如何在python中优雅地交错两个不均匀长度的列表?

Jac*_*ley 12 python list python-3.x

我想在python中合并两个列表,列表具有不同的长度,因此较短列表的元素在最终列表中的间隔尽可能相等.即我想采取[1, 2, 3, 4]['a','b']合并它们以获得类似的列表[1, 'a', 2, 3, 'b', 4].它需要能够与那些不准确的倍数太名单功能,所以它可以采取[1, 2, 3, 4, 5]['a', 'b', 'c']生产[1, 'a', 2, 'b', 3, 'c', 4, 5]或相似.它需要保留两个列表的顺序.

我可以通过一个冗长的蛮力方法看到如何做到这一点但是因为Python似乎有很多优秀的工具可以做各种我不知道的聪明的事情(还)我想知道是否还有其他的东西优雅我可以使用?

注意:我使用的是Python 3.3.

unu*_*tbu 10

从Jon Clements的解决方案中大量借用,您可以编写一个函数,该函数接受任意数量的序列并返回均匀间隔项的合并序列:

import itertools as IT

def evenly_spaced(*iterables):
    """
    >>> evenly_spaced(range(10), list('abc'))
    [0, 1, 'a', 2, 3, 4, 'b', 5, 6, 7, 'c', 8, 9]
    """
    return [item[1] for item in
            sorted(IT.chain.from_iterable(
            zip(IT.count(start=1.0 / (len(seq) + 1), 
                         step=1.0 / (len(seq) + 1)), seq)
            for seq in iterables))]

iterables = [
    ['X']*2,
    range(1, 11),
    ['a']*3
    ]

print(evenly_spaced(*iterables))
Run Code Online (Sandbox Code Playgroud)

产量

[1, 2, 'a', 3, 'X', 4, 5, 'a', 6, 7, 'X', 8, 'a', 9, 10]
Run Code Online (Sandbox Code Playgroud)


Mic*_*ber 10

这与Bresenham的线算法基本相同.您可以计算"像素"位置并将其用作列表中的索引.

您的任务不同之处在于您只希望每个元素出现一次.您需要修改算法或对索引进行后处理,仅在列表第一次出现时附加列表中的元素.但是有一点点含糊不清:当两个像素/列表索引同时发生变化时,您需要选择首先包含哪一个.这对应于交错问题中提到的列表和注释的两个不同选项.


Jon*_*nts 7

假设a是要插入的序列:

from itertools import izip, count
from operator import itemgetter
import heapq

a = [1, 2, 3, 4]
b = ['a', 'b']

fst = enumerate(a)
snd = izip(count(0, len(a) // len(b)), b)
print map(itemgetter(1), heapq.merge(fst, snd))
# [1, 'a', 2, 3, 'b', 4]
Run Code Online (Sandbox Code Playgroud)


Joh*_*ooy 5

如果a是更长的列表,b则更短

from itertools import groupby

len_ab = len(a) + len(b)
groups = groupby(((a[len(a)*i//len_ab], b[len(b)*i//len_ab]) for i in range(len_ab)),
                 key=lambda x:x[0])
[j[i] for k,g in groups for i,j in enumerate(g)]
Run Code Online (Sandbox Code Playgroud)

例如

>>> a = range(8)
>>> b = list("abc")
>>> len_ab = len(a) + len(b)
>>> groups = groupby(((a[len(a)*i//len_ab], b[len(b)*i//len_ab]) for i in range(len_ab)), key=lambda x:x[0])
>>> [j[i] for k,g in groups for i,j in enumerate(g)]
[0, 'a', 1, 2, 'b', 3, 4, 5, 'c', 6, 7]
Run Code Online (Sandbox Code Playgroud)

您可以使用此技巧确保a时间长于b

b, a = sorted((a, b), key=len)
Run Code Online (Sandbox Code Playgroud)