2014-02-17 107 views
0

我試圖以特定順序遞歸地播放列表。以某種順序遞歸地隨機播放列表

我:

def shuffle(list1, list2): 
    a = [] 
    if len(list1) == 0: 
     a += list2 
     return a 
    if len(list2) == 0: 
     a += list1 
     return a 
    else: 
     a += [list1[0]] 
     list1.pop(0) 
     a += [list2[0]] 
     list2.pop(0) 
    return a += shuffle(list1, list2) 
+0

是你的問題,它的返回'none'? – ForgetfulFellow

回答

0
from itertools import chain 

def shuffle(list1, list2): 
    if len(list1)==len(list2): return list(chain(*zip(list1,list2))) 
    # if the lists are of equal length, chaining the zip will be faster 
    else: 
     a = [] 
     while any([list1,list2]): 
      for lst in (list1,list2): 
       try: a.append(lst.pop(0)) 
       except IndexError: pass 
     return a 
    # otherwise, so long as there's items in both list1 and list2, pop the 
    # first index of each (ignoring IndexError since one might be empty) 
    # in turn and append that to a, returning the value when both lists are 
    # empty. 

這是不是你要找的遞歸解決方案,而是一個明確的一個通常是更快,更容易閱讀和調試反正。 @DSM指出這可能是一個家庭作業問題,所以我對誤讀表示歉意。我會繼續留下來,以防萬一它對任何人都有啓發。

+0

由於OP反覆提到遞歸,我懷疑這是一個基於zip的解決方案無法幫助的分配問題。 – DSM

+0

@DSM我會說實話,我撇清了這個問題。遞歸解決方案几乎從來都不是正確的,但不可避免地是學術性的。我不明白.... –

3

你的核心問題是你沒有返回你的遞歸調用。清理一些在你的代碼在名義上未使用的當地人給:

def shuffle(list1, list2): 
    a = [] 
    if len(list1) == 0: 
     return list2 
    if len(list2) == 0: 
     return list1 
    else: 
     a.append(list1.pop(0)) 
     a.append(list2.pop(0)) 
    return a + shuffle(list1, list2) 

當然,在上述清理很明顯,你甚至都不需要a蓄電池:

def shuffle(list1, list2): 
    if len(list1) == 0: 
     return list2 
    if len(list2) == 0: 
     return list1 
    else: 
     return [list1.pop(0),list2.pop(0)] + shuffle(list1, list2) 

演示:

shuffle([1,2,3],[4,5,6]) 
Out[35]: [1, 4, 2, 5, 3, 6] 

shuffle([1,2], [6,7,8,9]) 
Out[36]: [1, 6, 2, 7, 8, 9] 

順便說一句,這會改變輸入列表,這通常不是所希望的。使用遞歸模型

def shuffle(list1, list2): 
    if len(list1) == 0: 
     return list2 
    if len(list2) == 0: 
     return list1 
    else: 
     return [list1[0],list2[0]] + shuffle(list1[1:], list2[1:]) 
+0

漂亮!偉大的工作配對索引,直到一個列表爲空,然後返回完整列表。我不認爲我會想到這一點。 –

+0

>「通過使用切片而不是彈出可以更好地服務」。 不是每個切片都不會生成原始列表的副本減去一個元素嗎?這是pythonic,但似乎有很多開銷。 – solidpixel

+1

@ Isogen74是的。我認爲,如果你在Python中使用遞歸,你不關心性能:-) – roippi

0

我怎樣才能使此功能工作這些情況:您可以通過使用切片,而不是pop平掉元素得到更好的服務?

對於遞歸中兩個列表非空的每一步,您正在創建一個新的臨時數組「a」,但隨後不會執行任何操作。

您需要通過遞歸鏈(首選 - 它是零拷貝)傳遞存儲結果的列表,或者返回列表片段並在展開遞歸時將其附加到結果數組中(功能性,但需要每次創建一個新的列表對象,這很慢)。

0

發電機版本,只是因爲發電機真棒^^

def shuffle(a,b): 
    A = iter(a) 
    B = iter(b) 

    while True: 
     try: 
      yield A.next() 
     except StopIteration: 
      for j in B: 
       yield j 
      break 
     try: 
      yield B.next() 
     except StopIteration: 
      for j in A: 
       yield j 
      break 

print list(shuffle(a,b))