Пропуск дублируется при генерации комбинаций

#python

#python

Вопрос:

У меня есть этот код:

 from collections import Counter
def groups(d, l, c = []):
   if l == len(c):
     yield c
   else:
      for i in d:
         if i not in c:
            _c = Counter([j for k in [*c, i] for j in k])
            if all(j < 3 for j in _c.values()):
               yield from groups(d, l, c [i])

data = [(1,2),(2,3),(2,4),(2,5),(2,6),(3,1),(3,2),(3,4)]
result = list(groups(data, 3))
  

Этот код генерирует тройки пар, подобных этому:
[[(1, 2), (2, 3), (3, 1)], [(1, 2), (2, 3), (3, 4)], [(1, 2), (2, 4), (3, 1)],1[(1, 2), (2, 4), (3, 4)], [(1, 2), (2, 5), (3, 1)], [(1, 2), (2, 5), (3, 4)] ...

Проблема в том, что существуют дубликаты, подобные этому:

[(1, 2), (2, 3), (3, 1)] and [(2, 3), (1, 2), (3, 1)]

Есть ли способ избежать их в процессе генерации?

Комментарии:

1. Хотите ли вы изменить текущий код или просто удалить дубликаты из результата?

2. Измените код.

Ответ №1:

Вы изобретаете колесо. Просто используйте itertools.combinations :

 from itertools import combinations

data = [(1, 2), (2, 3), (2, 4), (2, 5), (2, 6), (3, 1), (3, 2), (3, 4)]
print(list(combinations(data, 3)))
# [((1, 2), (2, 3), (2, 4)), ((1, 2), (2, 3), (2, 5)), ...
  

Вы можете подтвердить, что в этом нет повторений, проверив длину возвращаемого списка (которая равна 56), что является именно тем, что вы ожидаете (8 выберите 3 равно 56)

Если вам нужно применить пользовательскую логику, вы все равно можете это сделать:

 from itertools import combinations

data = [(1, 2), (2, 3), (2, 4), (2, 5), (2, 6), (3, 1), (3, 2), (3, 4)]

wanted_combinations = []
for combination in combinations(data, 3):
    # apply logic
    if condition:
        wanted_combinations.append(combination)
  

Комментарии:

1. Мне нужен особый результат, как в примере, а не комбинации.

2. @M.Barabas Вы можете применить логику к возвращенному генератору из combinations . Вы получите правильный результат и лучшую производительность ( combinations реализовано на C), как видно из моего обновленного ответа

3. Я не могу просмотреть все комбинации, я работаю с массивом размером 50 и генерирую 23-ные числа, мне нужно изменить код, чтобы генерировать только необходимые тройки.

4. @M.Barabas В этом случае, я думаю, вы столкнетесь с теми же проблемами производительности в любом случае. 50 выберите 23 — это 108,043,253,365,600

5. Да, это правда, но когда я пропущу nти в соответствии с условием в процессе генерации, количество nти будет намного меньше.