簡體   English   中英

防止重復 itertools.permutations

[英]Prevent duplicates from itertools.permutations

我想使用 2 A 和 2 B 獲得 4 個字符串的所有唯一排列

from itertools import permutations

perm = permutations('AABB', 4)
for i in list(perm):
    print(i)

這讓我

('A', 'A', 'B', 'B')
('A', 'A', 'B', 'B')
('A', 'B', 'A', 'B')
('A', 'B', 'B', 'A')
...

如您所見,我得到了重復項。 我想這是因為它認為第一名和第二名的 A 是不同的值,但對我來說 AABB 只是 1 個獨特的結果。

我可以通過將所有這些都放入一個集合中以擺脫重復來解決此結果,但我認為我只是使用錯誤的排列函數。

我如何使用排列函數來獲得所有獨特的排列,使用 2 A 和 2 B 而不會得到 dups?

在 itertools 中沒有直接的方法可以做到這一點。 permutations()的文檔指出:

元素根據它們的位置而不是它們的值被視為唯一的。

這意味着盡管兩個A看起來與您相等,但 itertools 將它們視為不相等,因為它們在原始字符串中具有不同的位置。

您想要的結果數稱為 4 個值的多項式系數,其中 2 個相等,另外 2 個相等。 您可以通過將自己的等效函數編碼為permutations來獲得所需的內容,但這需要一段時間來編碼和調試。 (也許稱它為multinomial ,雖然這個詞指的是一個數字,而不是實際的列表。)一種更簡單的方法,可能在執行和內存使用上較慢,但在編程中要快得多,是使用permutations和 Python 的set來刪除重復項。 你可以這樣做:

from itertools import permutations

perm = permutations('AABB', 4)
for i in set(perm):
    print(i)

這可能會導致打印輸出的順序不同。 如果要恢復原始順序,請使用sorted(set(perm)) ,因為permutations按字典順序返回(如果您的原始字符串按排序順序)。

您可以迭代set或使用hashing

from itertools import permutations, combinations

perm = set(permutations('AABB', 4))
for i in <b>perm</b>:
    print(i)

#Output
('A', 'A', 'B', 'B')
('A', 'B', 'A', 'B')
('A', 'B', 'B', 'A')
('B', 'A', 'A', 'B')
('B', 'B', 'A', 'A')
('B', 'A', 'B', 'A')  

使用字典:

from itertools import permutations, combinations
dicta = {}
perm = permutations('AABB', 4)
for i in list(perm):
    if i in dicta:
        dicta[i] += 1
    else:
        dicta[i] = 1
print([i for i in dicta.keys()])

您應該使用more_itertools.distinct_permutations來實現這一點。

from more_itertools import distinct_permutations as idp
for p in idp('ABB'):
    print(p)

你說得非常對, itertools將元素放在它們的positions而不是它們的values上 - 因此,它不支持刪除這些類型的重復......

我們從the documentation指出:

元素根據它們的位置而不是它們的值被視為唯一的。 因此,如果輸入元素是唯一的,則每個排列中不會有重復值。

這給我們留下了兩個選擇,要么編寫自己的function ,要么轉換為set而不是list

from itertools import permutations

perm = permutations('AABB', 4)
for i in set(perm):
    print(i)

outputs

('A', 'B', 'B', 'A')
('B', 'A', 'B', 'A')
('B', 'B', 'A', 'A')
('A', 'B', 'A', 'B')
('A', 'A', 'B', 'B')
('B', 'A', 'A', 'B')

請注意,無需將set轉換回list ,因為您可以iterate set

上面的輸出沒有錯。首先了解排列是如何工作的。

s = "AA"

對於上面的字符串,排列將給出 2 個字符串。

AA and AA

上述兩個字符串是完全有效的,因為

1st      2nd
 A        A      --->this is first output.

2nd      1st
 A        A    ----> this is 2nd one.

排列所做的只是替換字符的位置。 不幸的是,它不檢查任何重復項。 要刪除重復項,您可以使用集合,因為集合不允許任何重復值。

myList = ["AA", "AB", "AA"]
set(myList)
output---> "AA", "AB"

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM