2017-01-11 3 views
-1

Учитывая список, я хочу все перестановки определенной длины, но только те, которые остаются отсортированными.Как получить все отсортированные перестановки в Python

Так, если список

[1,1,3,4] 

, то ответ с длиной 2 является

[[1,1], [1,1], [1,3], [1,3] [3,4], [1,4], [1,4]] 

Просьба предоставить эффективный ответ.

+0

Почему вы должны '[1,3]' 'дважды, но [1,1]' только один раз? Как вы хотите лечить дубликаты? –

+0

Итак, вы не хотите удалять дубликаты? Тогда ответ от @Inbar отлично подходит. Просто сделайте 'sorted (r)' вместо того, чтобы кастинг для 'set' сначала. –

ответ

6
import itertools 

l = [1, 1, 3, 4] 
r = [perm for perm in itertools.permutations(l, 2) if sorted(perm) == list(perm)] 

приводит:

[(1, 1), (1, 3), (1, 4), (1, 1), (1, 3), (1, 4), (3, 4)] 

Если вы хотите, чтобы результаты отсортированы, и уникальные:

s = sorted(set(r)) # [(1, 1), (1, 3), (1, 4), (3, 4)] 

Если вы хотите, чтобы результаты как списки вместо кортежей, просто бросить их list()


Используя рецепт itertools.permutations я сделал эту функцию удобства для вас:

def sorted_perms(iterable, r=None): 
    pool = tuple(sorted(iterable)) 
    n = len(pool) 
    r = n if r is None else r 
    for indices in itertools.product(range(n), repeat=r): 
     if len(set(indices)) == r and tuple_is_sorted(indices): 
      yield tuple(pool[i] for i in indices) 

memo = {} # simple memoization for efficiency. 
def tuple_is_sorted(t): 
    return memo.setdefault(t, bool(sorted(t) == list(t))) 

r = list(sorted_perms(l, 2)) # [(1, 1), (1, 3), (1, 4), (1, 3), (1, 4), (3, 4)] 
s = sorted(set(r)) # [(1, 1), (1, 3), (1, 4), (3, 4)] 
+0

Будет ли сначала Python вычислять все перестановки, а затем удалять все несортированные? Разве это не так неэффективно? –

+0

@ImeanH Это будет, да и теоретически это неэффективно, но какие другие хорошие варианты у вас есть? –

+0

@ImeanH В ответ я дал да, вот что он будет делать, это был вопрос в OP. –

0

Вы можете использовать itertools.permutations и operator.le для фильтрации

import itertools 
import operator 

l = [1, 1, 3, 4] 

unique = filter(lambda x: operator.le(x[0], x[1]), itertools.permutations(l, 2)) 

print(sorted(unique)) 

Выход

[(1, 1), (1, 1), (1, 3), (1, 3), (1, 4), (1, 4), (3, 4)] 

Трансформирует списки

print([[a, b] for a, b in sorted(unique)]) 

Выход

[[1, 1], [1, 1], [1, 3], [1, 3], [1, 4], [1, 4], [3, 4]] 
Смежные вопросы