Python 两个列表的同质混合

Python 两个列表的同质混合,python,Python,我想以最同质的方式在python中混合两个不同长度的列表 a = [1,2,3] b = ['a', 'b', 'c', 'd', 'e', 'f'] a和b的合并列表应导致 c = ['a', 'b', 1, 'c', 'd', 2, 'e', 'f', 3] 如果len(b)/len(a)不是整数,有没有一种python方法可以合并这两个列表?如果len(b)/len(a)不是整数,那么就不可能正确地分配列表 这个问题更像是与算法相关的,而不是编码部分。要组合这两个列表,您需要首先找出模

我想以最同质的方式在python中混合两个不同长度的列表

a = [1,2,3]
b = ['a', 'b', 'c', 'd', 'e', 'f']
a和b的合并列表应导致

c = ['a', 'b', 1, 'c', 'd', 2, 'e', 'f', 3]
如果len(b)/len(a)不是整数,有没有一种python方法可以合并这两个列表?如果len(b)/len(a)不是整数,那么就不可能正确地分配列表

这个问题更像是与算法相关的,而不是编码部分。要组合这两个列表,您需要首先找出模式。如果a中有x个元素,b中有nx个元素,那么列表的长度将为x+nx。这意味着对于a中的每个元素,b中会有n个元素

因此,首先您需要找出这个
n
,这可以通过找出列表长度的比率来完成。然后在一个空列表中,添加模式1中的元素a中的元素,以及模式1中的n个元素b中的元素,依此类推,直到您拥有
c
中的所有元素

下面是一个小Python程序。您可以根据自己的喜好对其进行相应的修改

a = [1,2,3]
b = ['a', 'b', 'c', 'd', 'e', 'f']

i,j = 0,0
diff = len(b)//len(a) # int value
c = [] # Empty
tot_item = len(b) + len(a)
while tot_item != len(c):
    c += b[i:i+diff]
    c += a[j:j+1]
    i += diff
    j += 1
print c
输出

['a', 'b', 1, 'c', 'd', 2, 'e', 'f', 3]

这里有一种方法。我找到第一个列表的长度与第二个列表的长度之比
a:b
,用最低的术语表示,然后我通过交替第二个列表的
b
元素块,然后是第一个列表的
a
元素来建立列表:

import fractions
def mixLists(xs,ys):
    m = len(xs)
    n = len(ys)
    d = fractions.gcd(m,n)
    s = m//d
    t = n//d
    xslices = (xs[i:i+s] for i in range(0,m,s))
    yslices = (ys[i:i+t] for i in range(0,n,t))
    mixed = []
    for x,y in zip(xslices,yslices):
        mixed.extend(y)
        mixed.extend(x)
    return mixed
典型输出:

>>> a = [1,2,3]
>>> b = ['a','b','c','d','e','f']
>>> mixLists(a,b)
['a', 'b', 1, 'c', 'd', 2, 'e', 'f', 3]
>>> a = [1,2,3,4]
>>> mixLists(a,b)
['a', 'b', 'c', 1, 2, 'd', 'e', 'f', 3, 4]
如果长度之间有一个很好的比率
a:b
,此函数将返回一个列表,其中大小为
a+b
的连续切片将从两个列表中提取具有代表性的金额。但是——在长度相对素数的情况下,结果不是很均匀:

>>> a = [1,2,3,4,5]
>>> mixLists(a,b)
['a', 'b', 'c', 'd', 'e', 'f', 1, 2, 3, 4, 5]

你需要更仔细地考虑在这种情况下你想要什么。

这里有一种解释同质混合的方法:假设这两个列表的长度分别为m和n。将第一个列表中的元素放置在实线的子区间[0,1]上,每个元素之间的间距为1/m,间隔均匀。因此,我们可以将这些元素放置在0/m、1/m、2/m、…(m-1)/m的位置。但是,对于范围内的任何x,我们也可以将元素放置在x/m、(x+1)/m、(x+2)/m的位置[0,1).对第二个列表中的元素执行相同的操作,将它们彼此间隔1/n,以便所有元素再次包含在[0,1]中。现在要获得两个列表的均匀混合,请读取所有元素(从两个列表中)如果第一个列表和第二个列表中的元素在一个或多个点上完全重合,则每次出现时都优先考虑第一个列表

您可以相对轻松地编写此想法,经过一点简化后,您将以一个相当简短和优雅的内容结束。以下是生成混合列表中连续元素的生成器函数:

def mix_lists(l1, l2):
    """ Mix two lists evenly, generating the elements of the mixed list. """
    m, n = len(l1), len(l2)
    for i in range(m + n):
        q, r = divmod(i * n, m + n)
        yield l1[i - q] if r < m else l2[q]
还有几个例子不符合这一点:

>>> list(mix_lists('abcdefgh', range(12)))
['a', 0, 'b', 1, 2, 'c', 3, 'd', 4, 5, 'e', 6, 'f', 7, 8, 'g', 9, 'h', 10, 11]
>>> list(mix_lists('abcdefg', [1, 2, 3, 4]))
['a', 'b', 1, 'c', 'd', 2, 'e', 'f', 3, 'g', 4]
现在有一点变化,您可以在
divmod
调用中添加一个偏移量:该偏移量应该严格在
0的范围内

大列表确实必须放在第一位。将其包装在一个检查中,以确定一个对排序非常健壮的函数。

我在这里建立在@Mark Dickinson的答案之上。 我发现生成器比性能较差的版本更难理解:

def mix_lists(l1, l2):
    """ Mix two lists evenly, generating the elements of the mixed list. """
    _l1 = [(i / len(l1), v) for i, v in enumerate(l1)]
    _l2 = [(i / len(l2), v) for i, v in enumerate(l2)]
    return [v for i, v in sorted(_l1 + _l2)]
如果没有一些解释,我不会将任何一个版本引入代码库。
伟大的材料马克,完全使我的一天。

len(b)/len(a)
不是整数时,你想如何混合列表?此外,如果你已经尝试过任何东西,你也应该发布。把较长的列表分成两部分怎么样?将第一部分与另一部分混合,然后附加第二部分(未混合)混合列表的一部分。什么应该
a=[1,2,3,4];b=['a','b','c','d','e','f']
输出?你如何评估“最同质”呢?我在说“最同质”时的想法是什么:列表有
m
n
元素。如果我们在
x-y
平面中思考,完美的混合将产生一条从(0,0)到(m,n)的直线。该算法应以所选路径到直线的平方差最小的方式对这两种算法的元素进行排序。这是我关于齐次排序的微不足道的想法。欢迎更好的想法!我仍然坐在这里完全不知所措。先生,您需要更多的投票。
def mix_lists(l1, l2, offset=0):
    """ Mix two lists evenly, generating the elements of the mixed list. """
    m, n = len(l1), len(l2)
    for i in range(m + n):
        q, r = divmod(i * n + offset, m + n)
        yield l1[i - q] if r < m else l2[q]
>>> list(mix_lists('abcdefg', [1, 2, 3, 4], offset=0))
['a', 'b', 1, 'c', 'd', 2, 'e', 'f', 3, 'g', 4]
>>> list(mix_lists('abcdefg', [1, 2, 3, 4], offset=2))
['a', 'b', 1, 'c', 2, 'd', 'e', 3, 'f', 'g', 4]
>>> list(mix_lists('abcdefg', [1, 2, 3, 4], offset=5))
['a', 1, 'b', 'c', 2, 'd', 3, 'e', 'f', 4, 'g']
>>> list(mix_lists('abcdefg', [1, 2, 3, 4], offset=9))
[1, 'a', 'b', 2, 'c', 3, 'd', 'e', 4, 'f', 'g']
>>> mix_lists('abcdefg', [1, 2, 3, 4], offset=10)
[1, 'a', 2, 'b', 'c', 3, 'd', 'e', 4, 'f', 'g']
>>> list(mix_lists('abcd', [1, 2, 3]))
['a', 'b', 1, 'c', 2, 'd', 3]
>>> list(mix_lists('abcd', [1, 2, 3], offset=3))
['a', 1, 'b', 2, 'c', 3, 'd']
>>> list(mix_lists('abcd', [1, 2, 3], offset=6))
[1, 'a', 2, 'b', 3, 'c', 'd']
def homogenized(bigList,smallList):
    ratio=len(bigList)/len(smallList) #integer division, needs to change for python 3
    smallList.reverse()
    counter=0
    out=[]
    for element in bigList:
        out.append(element)
        counter=counter+1
        if counter==ratio:
            counter=0
            try:
                out.append(smallList.pop())
            except IndexError:
                pass
    return out

print homogenized(['a', 'b', 'c', 'd', 'e'], [1,2,3])
print homogenized(['a', 'b', 'c', 'd', 'e', 'f'], [1,2,3])
print homogenized(['a', 'b', 'c', 'd', 'e', 'f', 'g'], [1,2,3])



>>> 
['a', 1, 'b', 2, 'c', 3, 'd', 'e']
['a', 'b', 1, 'c', 'd', 2, 'e', 'f', 3]
['a', 'b', 1, 'c', 'd', 2, 'e', 'f', 3, 'g']
def mix_lists(l1, l2):
    """ Mix two lists evenly, generating the elements of the mixed list. """
    _l1 = [(i / len(l1), v) for i, v in enumerate(l1)]
    _l2 = [(i / len(l2), v) for i, v in enumerate(l2)]
    return [v for i, v in sorted(_l1 + _l2)]