#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ти будет намного меньше.