ben
Tengo una lista con 15 números. ¿Cómo puedo producir las 32.768 combinaciones de esos números (es decir, cualquier número de elementos, en el orden original)?
Pensé en recorrer los enteros decimales 1–32768 y usar la representación binaria de cada número como filtro para seleccionar los elementos de lista apropiados. Hay una mejor manera de hacerlo?
Para combinaciones de una longitud específica, consulte Obtener todas las combinaciones (n-elegir-k) de longitud n. Utilice esa pregunta para cerrar duplicados en su lugar cuando corresponda.
Al cerrar preguntas sobre combinatoria como duplicados, es muy importante asegurarse de qué OP realmente quiere, no las palabras que se usaron para describir el problema. Es extremadamente común que las personas que quieren, por ejemplo, un producto cartesiano (consulte Cómo obtener el producto cartesiano de varias listas) pregunten sobre “combinaciones”.
james brady
Mira esto itertools.combinaciones:
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.
¡Desde 2.6, las baterías están incluidas!
-
puedes enumerarlo todo.
list(itertools.combinations(iterable, r))
– silgón
14 de septiembre de 2017 a las 12:23
-
hay algo que no requiera
r
es decir, combinaciones de subsecuencias de elementos de cualquier longitud.– mlestudiante33
23 de mayo de 2020 a las 5:39
-
esto es muy bueno y me señaló lo que realmente resolvió mi problema, que fue
itertools.combination_with_replacement
.– usuario3348949
15 oct 2020 a las 23:39
-
la función escribe intertools.combinations_with_replacement
– Al Martins
3 sep 2021 a las 17:53
-
Cuál es el
list()
conversión para en primer lugar?– AMC
7 de diciembre de 2019 a las 4:47
-
@Alexander: para permitir que se determine la longitud del iterable.
– martineau
7 de diciembre de 2019 a las 8:37
-
… pero esto es esencialmente una refactorización de Dan H
all_subsets
código, simplemente usandochain.from_iterable(x)
en lugar dechain(*x)
.– Karl Knechtel
2 de marzo a las 0:26
ninjagecko
Aquí hay una sola línea perezosa, que también usa itertools:
from itertools import compress, product
def combinations(items):
return ( set(compress(items,mask)) for mask in product(*[[0,1]]*len(items)) )
# alternative: ...in product([0,1], repeat=len(items)) )
Idea principal detrás de esta respuesta: hay 2 ^ N combinaciones, igual que el número de cadenas binarias de longitud N. Para cada cadena binaria, elige todos los elementos correspondientes a un “1”.
items=abc * mask=###
|
V
000 ->
001 -> c
010 -> b
011 -> bc
100 -> a
101 -> a c
110 -> ab
111 -> abc
Cosas para considerar:
- Esto requiere que pueda llamar
len(...)
enitems
(solución alternativa: siitems
es algo así como un iterable como un generador, primero conviértalo en una lista conitems=list(_itemsArg)
) - Esto requiere que el orden de iteración en
items
no es aleatorio (solución: no te vuelvas loco) - Esto requiere que los artículos sean únicos, o de lo contrario
{2,2,1}
y{2,1,1}
ambos colapsarán a{2,1}
(solución alternativa: usarcollections.Counter
como reemplazo directo paraset
; es básicamente un conjunto múltiple … aunque es posible que necesite usarlo más adelantetuple(sorted(Counter(...).elements()))
si necesita que sea hashable)
Manifestación
>>> list(combinations(range(4)))
[set(), {3}, {2}, {2, 3}, {1}, {1, 3}, {1, 2}, {1, 2, 3}, {0}, {0, 3}, {0, 2}, {0, 2, 3}, {0, 1}, {0, 1, 3}, {0, 1, 2}, {0, 1, 2, 3}]
>>> list(combinations('abcd'))
[set(), {'d'}, {'c'}, {'c', 'd'}, {'b'}, {'b', 'd'}, {'c', 'b'}, {'c', 'b', 'd'}, {'a'}, {'a', 'd'}, {'a', 'c'}, {'a', 'c', 'd'}, {'a', 'b'}, {'a', 'b', 'd'}, {'a', 'c', 'b'}, {'a', 'c', 'b', 'd'}]
Este es un enfoque que se puede transferir fácilmente a todos los lenguajes de programación compatibles con la recursividad. (sin itertools, sin rendimiento, sin comprensión de lista):
def combs(a):
if len(a) == 0:
return [[]]
cs = []
for c in combs(a[1:]):
cs += [c, c+[a[0]]]
return cs
>>> combs([1,2,3,4,5])
[[], [1], [2], [2, 1], [3], [3, 1], [3, 2], ..., [5, 4, 3, 2, 1]]
darxtrix
Aquí hay uno usando recursividad:
>>> import copy
>>> def combinations(target,data):
... for i in range(len(data)):
... new_target = copy.copy(target)
... new_data = copy.copy(data)
... new_target.append(data[i])
... new_data = data[i+1:]
... print new_target
... combinations(new_target,
... new_data)
...
...
>>> target = []
>>> data = ['a','b','c','d']
>>>
>>> combinations(target,data)
['a']
['a', 'b']
['a', 'b', 'c']
['a', 'b', 'c', 'd']
['a', 'b', 'd']
['a', 'c']
['a', 'c', 'd']
['a', 'd']
['b']
['b', 'c']
['b', 'c', 'd']
['b', 'd']
['c']
['c', 'd']
['d']
-
¿Se puede modificar esto para devolver una lista de listas en lugar de imprimir?
– James Vickery
9 de noviembre de 2017 a las 2:14
-
@JamesVickery sí, podría considerar hacer una lista fuera de la función y agregarla, o (mejor) hacer que la función sea un generador, eche un vistazo a la palabra clave ‘rendimiento’ 🙂
– Cuervo de peligro
12 de noviembre de 2017 a las 14:01
-
new_data = copy.copy(data)
– esta fila es redundante por lo que veo, no influye en nada– Dmitriy Fialkovskiy
25 de octubre de 2018 a las 14:27
Los lectores deben tener en cuenta que si los elementos de la lista son único es una consideración extremadamente importante, ya que muchos algoritmos contarán en exceso algún subconjunto (por ejemplo, ‘abccc’ -> [”, ‘a’, ‘b’, ‘c’, ‘c’, ‘c’, ‘ac’, ‘ac’, ‘ac’, …]. Una solución fácil es empujar todos los elementos en un conjunto antes obtener sus permutaciones.
– ninjagecko
14 de septiembre de 2015 a las 0:23
@ninjagecko Usar la biblioteca Set no es eficiente ya que cada uno es O (n) en el mejor de los casos. ¡Por lo tanto, agregar n funciones a un conjunto es en realidad O (n ^ 2)!
– SM Biggs
11 de febrero de 2020 a las 6:02
Al leer detenidamente la pregunta, parece que el OP está pidiendo el Set de poder de su lista de 15 números, no todas las combinaciones. Creo que esta puede ser la razón por la que las respuestas están por todas partes.
– SM Biggs
11 de febrero de 2020 a las 6:53
@Scott Biggs: ¿estás seguro de que estás hablando de Python aquí? Establecer inserciones y búsquedas son O (1) caso promedio. Son como diccionarios. Usan hashing. Python no tiene una biblioteca de conjuntos especial (está en la biblioteca estándar). Estamos insertando números aquí, no funciones. (Todavía sería ineficiente usar la memoria O (2 ^ n); la solución adecuada para las personas que desean combinaciones en lugar del conjunto de potencia es una implementación recursiva simple, o
product
etc.)– ninjagecko
12 de febrero de 2020 a las 9:36