2014-01-26 80 views
0

我試圖創建一個函數,它接受元素列表並遞歸返回包含該列表的所有排列(長度爲r)的列表。但是,如果列表中有-1,則應該可以重複。我想要返回的[0,-1],[-1,0],[0,2],[2,0],[0,1],[ ],[-1,2],[2,-1]和[-1,-1]。具有重複元素的排列列表

這是到目前爲止我的功能:

def permutations(i, iterable, used, current, comboList, r): 
    if (i == len(iterable): 
     return 
    if (len(current) == r): 
     comboList.append(current) 
     print current 
     return 
    elif (used[i] != 1): 
     current.append(iterable[i]) 
     if (iterable[i][0] != -1): 
      used[i] = 1 
    for j in range(0, len(iterable)): 
     permutations(j+1, iterable, used, current, comboList, r) 
     used[i] = 0 
    return comboList 

正如你所看到的,我錯誤地試圖保持跟蹤已經和尚未訪問過的列表中元素的利用了「訪問列表」 。

+0

'-1'是一個醜陋的價值給予特殊待遇Python編寫的。你真的想做什麼?這些數字代表什麼? –

回答

1

有可能是一個更合適的方法,但這樣的事情完全未經測試的代碼:

def apply_mask(mask, perm): 
    return [perm.pop() if m else -1 for m in mask] 

def permutations(iterable, r): 
    if -1 not in iterable: 
     # easy case 
     return map(list, itertools.permutations(iterable, r))) 
    iterable = [x for x in iterable if x != -1] 
    def iter_values(): 
     for mask in itertools.product((True, False), repeat=r): 
      for perm in itertools.permutations(iterable, sum(mask)): 
       yield apply_mask(mask, list(perm)) 
    return list(iter_values()) 

也就是說:首先遍歷所有可能的「面具」,掩碼告訴你哪些元素將包含-1並將包含另一個值。然後,對於每個掩碼,遍歷「其他值」的所有排列。最後,使用apply_mask將值和-1插入結果的正確位置。

+0

這工作得很好!十分感謝你的幫助。我不會想到面具的概念,但它在這裏工作得非常好。真的,謝謝! – user3238710

0

槓桿itertools.permutations。你(顯然)想要使用任意數量的-1以及可能的其他元素的排列;但你想放棄重複。

我們可以通過簡單地提供與我們選擇的元素一樣多的-1來允許任意數量的-1。

我們可以通過使用一個集合來丟棄重複。

import itertools 
def unique_permutations_with_negative_ones(iterable, size): 
    # make a copy for inspection and modification. 
    candidates = tuple(iterable) 
    if -1 in candidates: 
     # ensure enough -1s. 
     candidates += ((-1,) * (size - candidates.count(-1))) 
    return set(itertools.permutations(candidates, size)) 

讓我們試一下:

>>> unique_permutations_with_negative_ones((0, -1, 2), 2) 
{(2, -1), (-1, 0), (-1, 2), (2, 0), (-1, -1), (0, -1), (0, 2)}