Esta es la solución más correcta que te podemos dar, sin embargo mírala pausadamente y valora si es compatible a tu trabajo.
Solución:
Sé que esto es tarde, pero quiero agregar un punto.
set(itertools.combinations(t, 4))
haría un buen trabajo para la mayoría de los casos, pero aún itera todas las combinaciones repetitivas internamente y, por lo tanto, puede ser computacionalmente pesado. Este es especialmente el caso si no hay muchas combinaciones únicas reales.
Este itera solo combinaciones únicas:
from itertools import chain,repeat,count,islice
from collections import Counter
def combinations_without_repetition(r, iterable=None, values=None, counts=None):
if iterable:
values, counts = zip(*Counter(iterable).items())
f = lambda i,c: chain.from_iterable(map(repeat, i, c))
n = len(counts)
indices = list(islice(f(count(),counts), r))
if len(indices) < r:
return
while True:
yield tuple(values[i] for i in indices)
for i,j in zip(reversed(range(r)), f(reversed(range(n)), reversed(counts))):
if indices[i] != j:
break
else:
return
j = indices[i]+1
for i,j in zip(range(i,r), f(count(j), counts[j:])):
indices[i] = j
Uso:
>>> t = [2,2,2,2,4]
# elements in t must be hashable
>>> list(combinations_without_repetition(4, iterable=t))
[(2, 2, 2, 2), (2, 2, 2, 4)]
# You can pass values and counts separately. For this usage, values don't need to be hashable
# Say you have ['a','b','b','c','c','c'], then since there is 1 of 'a', 2 of 'b', and 3 of 'c', you can do as follows:
>>> list(combinations_without_repetition(3, values=['a','b','c'], counts=[1,2,3]))
[('a', 'b', 'b'), ('a', 'b', 'c'), ('a', 'c', 'c'), ('b', 'b', 'c'), ('b', 'c', 'c'), ('c', 'c', 'c')]
# combinations_without_repetition() is a generator (and thus an iterator)
# so you can iterate it
>>> for comb in combinations_without_repetition(4, t):
... print(sum(comb))
...
8 # 2+2+2+2
10 # 2+2+2+4
Tenga en cuenta que itertools.combinations()
está implementado en C, lo que significa que es mucho más rápido que mi script de Python para la mayoría de los casos. Este código funciona mejor que set(itertools.combinations())
método sólo cuando hay MUCHAS MÁS combinaciones repetitivas que combinaciones únicas.
Como Donkey Kong apunta al conjunto, puede obtener los valores únicos en una lista al convertir la lista en un conjunto:
t = [2,2,2,2,4]
c = list(itertools.combinations(t, 4))
unq = set(c)
print(unq)
Y el resultado será:
(2, 2, 2, 4), (2, 2, 2, 2)
Si desea usarlo como una lista, puede volver a convertirlo haciendo:
result = list(unq)
La forma alternativa y más limpia y completa será:
t = [2,2,2,2,4]
c = set(itertools.combinations(t, 4))
Técnicamente, lo que obtienes en realidad no son duplicados, es simplemente cómo itertools.combinations
funciona, si lees la descripción en la página vinculada:
itertools.combinations(iterable, r)
Devuelve r subsecuencias de elementos de la entrada iterable.
Las combinaciones se emiten en orden de clasificación lexicográfico. Entonces, si la entrada iterable está ordenada, las tuplas de combinación se producirán en orden ordenado.
Los elementos se tratan como únicos en función de su posición, no de su valor. Entonces, si los elementos de entrada son únicos, no habrá valores repetidos en cada combinación.
MANIFESTACIÓN:
>>> import itertools as it
>>> list(it.combinations([1,2,3,4,5], 4))
[(1, 2, 3, 4), (1, 2, 3, 5), (1, 2, 4, 5), (1, 3, 4, 5), (2, 3, 4, 5)]
Entonces, tal como se publicó en la respuesta anterior, set()
le dará los valores únicos que desea:
>>> set(it.combinations(t, 4))
(2, 2, 2, 4), (2, 2, 2, 2)