Я принимаю ответ Гарета Риса как наиболее привлекательное объяснение (если не считать ответа от разработчиков библиотеки Python), а именно, что itertools.permutations
в Python не сравнивает значения элементов. Если подумать, это вопрос, о котором спрашивается, но теперь я вижу, как это можно рассматривать как преимущество, в зависимости от того, для чего обычно используется itertools.permutations
.
Просто для полноты я сравнил три метода генерации всех различных перестановок. Метод 1, который очень неэффективен в отношении памяти и времени, но требует наименьшего количества нового кода, состоит в том, чтобы обернуть itertools.permutations
Python, как в ответе Zeekay. Метод 2 - это основанная на генераторе версия C ++ next_permutation
, из этого сообщения в блоге . Метод 3 - это то, что я написал, это даже ближе к алгоритму C ++ next_permutation
; он изменяет список на месте (я не сделал его слишком общим).
def next_permutationS(l):
n = len(l)
#Step 1: Find tail
last = n-1 #tail is from `last` to end
while last>0:
if l[last-1] < l[last]: break
last -= 1
#Step 2: Increase the number just before tail
if last>0:
small = l[last-1]
big = n-1
while l[big] <= small: big -= 1
l[last-1], l[big] = l[big], small
#Step 3: Reverse tail
i = last
j = n-1
while i < j:
l[i], l[j] = l[j], l[i]
i += 1
j -= 1
return last>0
Вот некоторые результаты. Теперь я еще больше уважаю встроенную функцию Python: она примерно в три-четыре раза быстрее других методов, когда все элементы (или почти все) различны. Конечно, когда есть много повторяющихся элементов, использовать его - ужасная идея.
Some results ("us" means microseconds):
l m_itertoolsp m_nextperm_b m_nextperm_s
[1, 1, 2] 5.98 us 12.3 us 7.54 us
[1, 2, 3, 4, 5, 6] 0.63 ms 2.69 ms 1.77 ms
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10] 6.93 s 13.68 s 8.75 s
[1, 2, 3, 4, 6, 6, 6] 3.12 ms 3.34 ms 2.19 ms
[1, 2, 2, 2, 2, 3, 3, 3, 3, 3] 2400 ms 5.87 ms 3.63 ms
[1, 1, 1, 1, 1, 1, 1, 1, 1, 2] 2320000 us 89.9 us 51.5 us
[1, 1, 2, 2, 3, 3, 4, 4, 4, 4, 4, 4] 429000 ms 361 ms 228 ms
Код здесь , если кто-то хочет исследовать.