Грубо так же быстро, как и ответ Луки Ране, но короче & amp; более простой, IMHO.
def unique_permutations(elements):
if len(elements) == 1:
yield (elements[0],)
else:
unique_elements = set(elements)
for first_element in unique_elements:
remaining_elements = list(elements)
remaining_elements.remove(first_element)
for sub_permutation in unique_permutations(remaining_elements):
yield (first_element,) + sub_permutation
>>> list(unique_permutations((1,2,3,1)))
[(1, 1, 2, 3), (1, 1, 3, 2), (1, 2, 1, 3), ... , (3, 1, 2, 1), (3, 2, 1, 1)]
Он работает рекурсивно, устанавливая первый элемент (итерируя через все уникальные элементы) и повторяя через перестановки для всех остальных элементов.
Давайте пройдем unique_permutations
of (1,2,3,1), чтобы увидеть, как он работает:
unique_elements
- 1,2,3 first_element
начинается с 1. remaining_elements
- [2,3,1] (т. е. 1,2,3,1 минус первый 1). Мы перебираем (рекурсивно) через перестановки остальных элементов: (1, (3, 1, 2), (3, 2, 1). Для каждого sub_permutation
мы вставляем first_element
: (1,1,2,3), (1,1,3,2), ... и получаем результат. first_element
= 2 и делаем то же, что и выше. remaining_elements
- [1,3,1] (т. е. 1,2,3,1 минус первые 2). Мы перебираем через перестановки остальных элементов: (1, 1, 3), (1, 3, 1 ), (3, 1, 1) Для каждого sub_permutation
вставляем first_element
: (2, 1, 1, 3), (2, 1, 3, 1), (2, 3, 1, 1 ) ... и дать результат. first_element
= 3.