2014-07-05 39 views
0

我在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'] 

因此,代碼的作品,但它似乎並不像一個很好的辦法做到這一點。有沒有更好的辦法?

回答

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
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功能:該功能簡單地提供給它作爲參數成一個單一的迭代的迭代器/迭代的鏈的一個列表(未蟒列表)。

如:

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

儘管此代碼可以回答這個問題,答案會更有益的,如果你能解釋一下什麼是代碼在做什麼,爲什麼這是解決的最好辦法問題。 – MattDMo

+0

當然,我會更新答案。 –

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)