Dado un conjunto
{0, 1, 2, 3}
¿Cómo puedo producir los subconjuntos?
[set(),
{0},
{1},
{2},
{3},
{0, 1},
{0, 2},
{0, 3},
{1, 2},
{1, 3},
{2, 3},
{0, 1, 2},
{0, 1, 3},
{0, 2, 3},
{1, 2, 3},
{0, 1, 2, 3}]
La itertools
página de Python tiene exactamente una powerset
receta para esto:
from itertools import chain, combinations
def powerset(iterable):
"powerset([1,2,3]) --> () (1,) (2,) (3,) (1,2) (1,3) (2,3) (1,2,3)"
s = list(iterable)
return chain.from_iterable(combinations(s, r) for r in range(len(s)+1))
Salida:
>>> list(powerset("abcd"))
[(), ('a',), ('b',), ('c',), ('d',), ('a', 'b'), ('a', 'c'), ('a', 'd'), ('b', 'c'), ('b', 'd'), ('c', 'd'), ('a', 'b', 'c'), ('a', 'b', 'd'), ('a', 'c', 'd'), ('b', 'c', 'd'), ('a', 'b', 'c', 'd')]
Si no le gusta esa tupla vacía al principio, puede cambiar la range
declaración a range(1, len(s)+1)
para evitar una combinación de longitud 0.
s = list(iterable)
necesita?__len__
implementado; Pruébelopowerset((n for n in range(3)))
sin envolver la lista.powerset(range(3))
funcionaría bien incluso sins = list(iterable)
.Aquí hay más código para un powerset. Esto está escrito desde cero:
>>> def powerset(s): ... x = len(s) ... for i in range(1 << x): ... print [s[j] for j in range(x) if (i & (1 << j))] ... >>> powerset([4,5,6]) [] [4] [5] [4, 5] [6] [4, 6] [5, 6] [4, 5, 6]
El comentario de Mark Rushakoff es aplicable aquí: "Si no te gusta esa tupla vacía al principio, encendido". Puedes cambiar la declaración de rango a rango (1, len (s) +1) para evitar una combinación de longitud 0 ", excepto que en mi caso cambia
for i in range(1 << x)
afor i in range(1, 1 << x)
.Volviendo a esto años más tarde, ahora lo escribiría así:
def powerset(s): x = len(s) masks = [1 << i for i in range(x)] for i in range(1 << x): yield [ss for mask, ss in zip(masks, s) if i & mask]
Y luego el código de prueba se vería así, di:
print(list(powerset([4, 5, 6])))
Usar
yield
significa que no es necesario calcular todos los resultados en una sola pieza de memoria. Se supone que el cálculo previo de las máscaras fuera del bucle principal es una optimización útil.fuente
Si está buscando una respuesta rápida, acabo de buscar "Python Power Set" en Google y se me ocurrió esto: Python Power Set Generator
Aquí hay una copia y pegado del código en esa página:
def powerset(seq): """ Returns all the subsets of this set. This is a generator. """ if len(seq) <= 1: yield seq yield [] else: for item in powerset(seq[1:]): yield [seq[0]]+item yield item
Esto se puede usar así:
l = [1, 2, 3, 4] r = [x for x in powerset(l)]
Ahora r es una lista de todos los elementos que deseaba, y se puede ordenar e imprimir:
r.sort() print r [[], [1], [1, 2], [1, 2, 3], [1, 2, 3, 4], [1, 2, 4], [1, 3], [1, 3, 4], [1, 4], [2], [2, 3], [2, 3, 4], [2, 4], [3], [3, 4], [4]]
fuente
[[][]]
, para solucionarlo, solo separe los casos para la verificación de longitudif len(seq) == 0: yield [] elif len(seq) == 1: yield seq yield []
def powerset(lst): return reduce(lambda result, x: result + [subset + [x] for subset in result], lst, [[]])
fuente
Hay un refinamiento de powerset:
def powerset(seq): """ Returns all the subsets of this set. This is a generator. """ if len(seq) <= 0: yield [] else: for item in powerset(seq[1:]): yield [seq[0]]+item yield item
fuente
TL; DR (vaya directamente a Simplificación)
Sé que he agregado una respuesta anteriormente, pero realmente me gusta mi nueva implementación. Estoy tomando un conjunto como entrada, pero en realidad podría ser cualquier iterable, y estoy devolviendo un conjunto de conjuntos que es el conjunto de potencia de la entrada. Me gusta este enfoque porque está más alineado con la definición matemática de conjunto de potencia ( conjunto de todos los subconjuntos ).
def power_set(A): """A is an iterable (list, tuple, set, str, etc) returns a set which is the power set of A.""" length = len(A) l = [a for a in A] ps = set() for i in range(2 ** length): selector = f'{i:0{length}b}' subset = {l[j] for j, bit in enumerate(selector) if bit == '1'} ps.add(frozenset(subset)) return ps
Si desea exactamente el resultado que publicó en su respuesta, use esto:
>>> [set(s) for s in power_set({1, 2, 3, 4})] [{3, 4}, {2}, {1, 4}, {2, 3, 4}, {2, 3}, {1, 2, 4}, {1, 2}, {1, 2, 3}, {3}, {2, 4}, {1}, {1, 2, 3, 4}, set(), {1, 3}, {1, 3, 4}, {4}]
Explicación
Se sabe que el número de elementos del conjunto de potencia es
2 ** len(A)
, por lo que se puede ver claramente en elfor
bucle.Necesito convertir la entrada (idealmente un conjunto) en una lista porque por conjunto hay una estructura de datos de elementos únicos desordenados, y el orden será crucial para generar los subconjuntos.
selector
es clave en este algoritmo. Tenga en cuenta queselector
tiene la misma longitud que el conjunto de entrada, y para que esto sea posible, está usando una cadena f con relleno. Básicamente, esto me permite seleccionar los elementos que se agregarán a cada subconjunto durante cada iteración. Digamos que el conjunto de entrada tiene 3 elementos{0, 1, 2}
, por lo que el selector tomará valores entre 0 y 7 (inclusive), que en binario son:000 # 0 001 # 1 010 # 2 011 # 3 100 # 4 101 # 5 110 # 6 111 # 7
Por lo tanto, cada bit podría servir como indicador si se debe agregar o no un elemento del conjunto original. Mire los números binarios y piense en cada número como un elemento del superconjunto, lo que
1
significa que un elemento en el índicej
debe agregar y0
que este elemento no se debe agregar.Estoy usando una comprensión de conjunto para generar un subconjunto en cada iteración, y convierto este subconjunto en un
frozenset
para poder agregarlo aps
(conjunto de potencia). De lo contrario, no podré agregarlo porque un conjunto en Python consiste solo en objetos inmutables.Simplificación
Puede simplificar el código usando algunas comprensiones de Python, para que pueda deshacerse de esos bucles for. También puede usar
zip
para evitar el uso dej
index y el código terminará como el siguiente:def power_set(A): length = len(A) return { frozenset({e for e, b in zip(A, f'{i:{length}b}') if b == '1'}) for i in range(2 ** length) }
Eso es. Lo que me gusta de este algoritmo es que es más claro e intuitivo que otros porque parece bastante mágico para confiar en
itertools
él, aunque funciona como se esperaba.fuente
def get_power_set(s): power_set=[[]] for elem in s: # iterate over the sub sets so far for sub_set in power_set: # add a new subset consisting of the subset at hand added elem power_set=power_set+[list(sub_set)+[elem]] return power_set
Por ejemplo:
get_power_set([1,2,3])
rendimiento
[[], [1], [2], [1, 2], [3], [1, 3], [2, 3], [1, 2, 3]]
fuente
power_set
) en el ciclo que gobierna es una práctica muy cuestionable. Por ejemplo, supongamos que usted escribió esto en vez de al código variable modificadora propuesta:power_set += [list(sub_set)+[elem]]
. Entonces el bucle no termina.He encontrado el siguiente algoritmo muy claro y simple:
def get_powerset(some_list): """Returns all subsets of size 0 - len(some_list) for some_list""" if len(some_list) == 0: return [[]] subsets = [] first_element = some_list[0] remaining_list = some_list[1:] # Strategy: get all the subsets of remaining_list. For each # of those subsets, a full subset list will contain both # the original subset as well as a version of the subset # that contains first_element for partial_subset in get_powerset(remaining_list): subsets.append(partial_subset) subsets.append(partial_subset[:] + [first_element]) return subsets
Otra forma de generar el conjunto de potencias es generando todos los números binarios que tienen
n
bits. Como conjunto de potencia, la cantidad de números conn
dígitos es2 ^ n
. El principio de este algoritmo es que un elemento podría estar presente o no en un subconjunto, ya que un dígito binario podría ser uno o cero, pero no ambos.def power_set(items): N = len(items) # enumerate the 2 ** N possible combinations for i in range(2 ** N): combo = [] for j in range(N): # test bit jth of integer i if (i >> j) % 2 == 1: combo.append(items[j]) yield combo
Encontré ambos algoritmos cuando estaba tomando MITx: 6.00.2x Introducción al pensamiento computacional y la ciencia de datos, y considero que es uno de los algoritmos más fáciles de entender que he visto.
fuente
Solo quería ofrecer la solución más comprensible, la versión anti-código-golf.
from itertools import combinations l = ["x", "y", "z", ] def powerset(items): combo = [] for r in range(len(items) + 1): #use a list to coerce a actual list from the combinations generator combo.append(list(combinations(items,r))) return combo l_powerset = powerset(l) for i, item in enumerate(l_powerset): print "All sets of length ", i print item
Los resultados
Todos los conjuntos de longitud 0
[()]
Todos los conjuntos de longitud 1
[('x',), ('y',), ('z',)]
Todos los conjuntos de longitud 2
[('x', 'y'), ('x', 'z'), ('y', 'z')]
Todos los conjuntos de longitud 3
[('x', 'y', 'z')]
Para obtener más información, consulte los documentos de itertools , también la entrada de wikipedia sobre conjuntos de potencia
fuente
¡Solo un repaso rápido del conjunto de energía!
Aquí hay otra forma de encontrar el conjunto de potencia:
def power_set(input): # returns a list of all subsets of the list a if (len(input) == 0): return [[]] else: main_subset = [ ] for small_subset in power_set(input[1:]): main_subset += [small_subset] main_subset += [[input[0]] + small_subset] return main_subset print(power_set([0,1,2,3]))
crédito completo a la fuente
fuente
Esto se puede hacer de forma muy natural con
itertools.product
:import itertools def powerset(l): for sl in itertools.product(*[[[], [i]] for i in l]): yield {j for i in sl for j in i}
fuente
Una forma sencilla sería aprovechar la representación interna de números enteros bajo aritmética de complemento a 2.
La representación binaria de números enteros es {000, 001, 010, 011, 100, 101, 110, 111} para números que van del 0 al 7. Para un valor de contador de números enteros, se considera 1 como inclusión del elemento correspondiente en la colección y '0' como exclusión podemos generar subconjuntos basados en la secuencia de conteo. Los números tienen que ser generado a partir
0
depow(2,n) -1
la que N es la longitud de la matriz es decir, número de bits en la representación binaria.Una función de generador de subconjuntos simple basada en ella se puede escribir como se muestra a continuación. Básicamente se basa
def subsets(array): if not array: return else: length = len(array) for max_int in range(0x1 << length): subset = [] for i in range(length): if max_int & (0x1 << i): subset.append(array[i]) yield subset
y luego se puede usar como
def get_subsets(array): powerset = [] for i in subsets(array): powerser.append(i) return powerset
Pruebas
Añadiendo lo siguiente en el archivo local
if __name__ == '__main__': sample = ['b', 'd', 'f'] for i in range(len(sample)): print "Subsets for " , sample[i:], " are ", get_subsets(sample[i:])
da la siguiente salida
Subsets for ['b', 'd', 'f'] are [[], ['b'], ['d'], ['b', 'd'], ['f'], ['b', 'f'], ['d', 'f'], ['b', 'd', 'f']] Subsets for ['d', 'f'] are [[], ['d'], ['f'], ['d', 'f']] Subsets for ['f'] are [[], ['f']]
fuente
Con un conjunto vacío, que es parte de todos los subconjuntos, puede usar:
def subsets(iterable): for n in range(len(iterable) + 1): yield from combinations(iterable, n)
fuente
Casi todas estas respuestas usan en
list
lugar deset
, lo que me pareció un poco engañoso. Entonces, por curiosidad, intenté hacer una versión simple realmente enset
y resumida para otras personas "nuevas en Python".Descubrí que hay un par de rarezas al tratar con la implementación de conjuntos de Python . La principal sorpresa para mí fue manejar sets vacíos. Esto contrasta con la implementación de Ruby's Set , donde simplemente puedo hacer
Set[Set[]]
y obtenerSet
uno que contenga uno vacíoSet
, por lo que inicialmente lo encontré un poco confuso.Para revisar, al hacer
powerset
conset
s, encontré dos problemas:set()
toma un iterable, porset(set())
lo que volveráset()
porque el conjunto vacío iterable está vacío (duh, supongo :))set({set()})
yset.add(set)
no funcionará porqueset()
no se puede mezclarPara resolver ambos problemas, utilicé
frozenset()
utilicé , lo que significa que no obtengo lo que quiero (el tipo es literalmenteset
), pero hace uso de laset
interacción general .def powerset(original_set): # below gives us a set with one empty set in it ps = set({frozenset()}) for member in original_set: subset = set() for m in ps: # to be added into subset, needs to be # frozenset.union(set) so it's hashable subset.add(m.union(set([member])) ps = ps.union(subset) return ps
A continuación, obtenemos 2² (16)
frozenset
s correctamente como salida:In [1]: powerset(set([1,2,3,4])) Out[2]: {frozenset(), frozenset({3, 4}), frozenset({2}), frozenset({1, 4}), frozenset({3}), frozenset({2, 3}), frozenset({2, 3, 4}), frozenset({1, 2}), frozenset({2, 4}), frozenset({1}), frozenset({1, 2, 4}), frozenset({1, 3}), frozenset({1, 2, 3}), frozenset({4}), frozenset({1, 3, 4}), frozenset({1, 2, 3, 4})}
Como no hay forma de tener una
set
deset
s en Python, si desea convertir estasfrozenset
s enset
s, tendrá que volver a mapearlas en alist
(list(map(set, powerset(set([1,2,3,4]))))
) o modificar lo anterior.fuente
Quizás la pregunta esté envejeciendo, pero espero que mi código ayude a alguien.
def powSet(set): if len(set) == 0: return [[]] return addtoAll(set[0],powSet(set[1:])) + powSet(set[1:]) def addtoAll(e, set): for c in set: c.append(e) return set
fuente
Utilice la función
powerset()
del paquetemore_itertools
.>>> list(powerset([1, 2, 3])) [(), (1,), (2,), (3,), (1, 2), (1, 3), (2, 3), (1, 2, 3)]
Si quieres conjuntos, usa:
fuente
Obteniendo todos los subconjuntos con recursividad. Una sola línea de culo loco
from typing import List def subsets(xs: list) -> List[list]: return subsets(xs[1:]) + [x + [xs[0]] for x in subsets(xs[1:])] if xs else [[]]
Basado en una solución de Haskell
fuente
NameError: name 'List' is not defined
List
importacióndef findsubsets(s, n): return list(itertools.combinations(s, n)) def allsubsets(s) : a = [] for x in range(1,len(s)+1): a.append(map(set,findsubsets(s,x))) return a
fuente
Puedes hacerlo así:
def powerset(x): m=[] if not x: m.append(x) else: A = x[0] B = x[1:] for z in powerset(B): m.append(z) r = [A] + z m.append(r) return m print(powerset([1, 2, 3, 4]))
Salida:
[[], [1], [2], [1, 2], [3], [1, 3], [2, 3], [1, 2, 3], [4], [1, 4], [2, 4], [1, 2, 4], [3, 4], [1, 3, 4], [2, 3, 4], [1, 2, 3, 4]]
fuente
Sé que es demasiado tarde
Ya hay muchas otras soluciones, pero aún así ...
def power_set(lst): pw_set = [[]] for i in range(0,len(lst)): for j in range(0,len(pw_set)): ele = pw_set[j].copy() ele = ele + [lst[i]] pw_set = pw_set + [ele] return pw_set
fuente
Esto es una locura porque ninguna de estas respuestas realmente proporciona el retorno de un conjunto de Python real. Aquí hay una implementación desordenada que dará un conjunto de poder que en realidad es un Python
set
.test_set = set(['yo', 'whatup', 'money']) def powerset( base_set ): """ modified from pydoc's itertools recipe shown above""" from itertools import chain, combinations base_list = list( base_set ) combo_list = [ combinations(base_list, r) for r in range(len(base_set)+1) ] powerset = set([]) for ll in combo_list: list_of_frozensets = list( map( frozenset, map( list, ll ) ) ) set_of_frozensets = set( list_of_frozensets ) powerset = powerset.union( set_of_frozensets ) return powerset print powerset( test_set ) # >>> set([ frozenset(['money','whatup']), frozenset(['money','whatup','yo']), # frozenset(['whatup']), frozenset(['whatup','yo']), frozenset(['yo']), # frozenset(['money','yo']), frozenset(['money']), frozenset([]) ])
Sin embargo, me encantaría ver una mejor implementación.
fuente
[*map(set, chain.from_iterable(combinations(s, r) for r in range(len(s)+1)))]
; la función arg demap
puede serfrozenset
si lo prefiere.Aquí está mi implementación rápida utilizando combinaciones pero usando solo incorporados.
def powerSet(array): length = str(len(array)) formatter = '{:0' + length + 'b}' combinations = [] for i in xrange(2**int(length)): combinations.append(formatter.format(i)) sets = set() currentSet = [] for combo in combinations: for i,val in enumerate(combo): if val=='1': currentSet.append(array[i]) sets.add(tuple(sorted(currentSet))) currentSet = [] return sets
fuente
Todos los subconjuntos en el rango n según lo establecido:
n = int(input()) l = [i for i in range (1, n + 1)] for number in range(2 ** n) : binary = bin(number)[: 1 : -1] subset = [l[i] for i in range(len(binary)) if binary[i] == "1"] print(set(sorted(subset)) if number > 0 else "{}")
fuente
import math def printPowerSet(set,set_size): pow_set_size =int(math.pow(2, set_size)) for counter in range(pow_set_size): for j in range(set_size): if((counter & (1 << j)) > 0): print(set[j], end = "") print("") set = ['a', 'b', 'c'] printPowerSet(set,3)
fuente
Una variación de la pregunta es un ejercicio que veo en el libro "Descubriendo la informática: problemas interdisciplinarios, principios y programación en Python. Edición de 2015". En ese ejercicio 10.2.11, la entrada es solo un número entero y la salida deben ser los conjuntos de potencias. Aquí está mi solución recursiva (sin usar nada más que python3 básico)
def powerSetR(n): assert n >= 0 if n == 0: return [[]] else: input_set = list(range(1, n+1)) # [1,2,...n] main_subset = [ ] for small_subset in powerSetR(n-1): main_subset += [small_subset] main_subset += [ [input_set[-1]] + small_subset] return main_subset superset = powerSetR(4) print(superset) print("Number of sublists:", len(superset))
Y la salida es
[[], [4], [3], [4, 3], [2], [4, 2], [3, 2], [4, 3, 2], [1], [4, 1 ], [3, 1], [4, 3, 1], [2, 1], [4, 2, 1], [3, 2, 1], [4, 3, 2, 1]] Número de sublistas: 16
fuente
No me había encontrado con la
more_itertools.powerset
función y recomendaría usarla. También recomiendo no usar el orden predeterminado de la salida deitertools.combinations
, a menudo, en cambio, desea minimizar la distancia entre las posiciones y ordenar los subconjuntos de elementos con una distancia más corta entre ellos arriba / antes de los elementos con una mayor distancia entre ellos.La
itertools
página de recetas muestra que usachain.from_iterable
r
aquí coincide con la notación estándar para la parte inferior de un coeficiente binomial ,s
generalmente se hace referencia a éln
en los textos de matemáticas y en las calculadoras ("n Elija r")def powerset(iterable): "powerset([1,2,3]) --> () (1,) (2,) (3,) (1,2) (1,3) (2,3) (1,2,3)" s = list(iterable) return chain.from_iterable(combinations(s, r) for r in range(len(s)+1))
Los otros ejemplos aquí dan el conjunto de potencias de
[1,2,3,4]
de tal manera que las 2 tuplas se enumeran en orden "lexicográfico" (cuando imprimimos los números como enteros). Si escribo la distancia entre los números a su lado (es decir, la diferencia), muestra mi punto:12 ⇒ 1 13 ⇒ 2 14 ⇒ 3 23 ⇒ 1 24 ⇒ 2 34 ⇒ 1
El orden correcto para los subconjuntos debe ser el orden que 'agota' la distancia mínima primero, así:
12 ⇒ 1 23 ⇒ 1 34 ⇒ 1 13 ⇒ 2 24 ⇒ 2 14 ⇒ 3
El uso de números aquí hace que este orden parezca "incorrecto", pero considere, por ejemplo, las letras
["a","b","c","d"]
, es más claro por qué esto podría ser útil para obtener el conjunto de potencias en este orden:ab ⇒ 1 bc ⇒ 1 cd ⇒ 1 ac ⇒ 2 bd ⇒ 2 ad ⇒ 3
Este efecto es más pronunciado con más elementos, y para mis propósitos marca la diferencia entre poder describir los rangos de los índices del conjunto de potencias de manera significativa.
(Hay mucho escrito en códigos Gray etc. para el orden de salida de los algoritmos en combinatoria, no lo veo como un problema secundario).
De hecho, acabo de escribir un programa bastante complicado que usó este código de partición de entero rápido para generar los valores en el orden correcto, pero luego descubrí
more_itertools.powerset
y para la mayoría de los usos probablemente esté bien usar esa función así:from more_itertools import powerset from numpy import ediff1d def ps_sorter(tup): l = len(tup) d = ediff1d(tup).tolist() return l, d ps = powerset([1,2,3,4]) ps = sorted(ps, key=ps_sorter) for x in ps: print(x)
⇣
() (1,) (2,) (3,) (4,) (1, 2) (2, 3) (3, 4) (1, 3) (2, 4) (1, 4) (1, 2, 3) (2, 3, 4) (1, 2, 4) (1, 3, 4) (1, 2, 3, 4)
Escribí algo de código más complicado que imprimirá el powerset muy bien (ver el repositorio de impresión bastante funciones que no he incluido aquí:
print_partitions
,print_partitions_by_length
, ypprint_tuple
).pset_partitions.py
Todo esto es bastante simple, pero aún puede ser útil si desea algún código que le permita acceder directamente a los diferentes niveles del conjunto de potencia:
from itertools import permutations as permute from numpy import cumsum # http://jeromekelleher.net/generating-integer-partitions.html # via # /programming/10035752/elegant-python-code-for-integer-partitioning#comment25080713_10036764 def asc_int_partitions(n): a = [0 for i in range(n + 1)] k = 1 y = n - 1 while k != 0: x = a[k - 1] + 1 k -= 1 while 2 * x <= y: a[k] = x y -= x k += 1 l = k + 1 while x <= y: a[k] = x a[l] = y yield tuple(a[:k + 2]) x += 1 y -= 1 a[k] = x + y y = x + y - 1 yield tuple(a[:k + 1]) # https://stackoverflow.com/a/6285330/2668831 def uniquely_permute(iterable, enforce_sort=False, r=None): previous = tuple() if enforce_sort: # potential waste of effort (default: False) iterable = sorted(iterable) for p in permute(iterable, r): if p > previous: previous = p yield p def sum_min(p): return sum(p), min(p) def partitions_by_length(max_n, sorting=True, permuting=False): partition_dict = {0: ()} for n in range(1,max_n+1): partition_dict.setdefault(n, []) partitions = list(asc_int_partitions(n)) for p in partitions: if permuting: perms = uniquely_permute(p) for perm in perms: partition_dict.get(len(p)).append(perm) else: partition_dict.get(len(p)).append(p) if not sorting: return partition_dict for k in partition_dict: partition_dict.update({k: sorted(partition_dict.get(k), key=sum_min)}) return partition_dict def print_partitions_by_length(max_n, sorting=True, permuting=True): partition_dict = partitions_by_length(max_n, sorting=sorting, permuting=permuting) for k in partition_dict: if k == 0: print(tuple(partition_dict.get(k)), end="") for p in partition_dict.get(k): print(pprint_tuple(p), end=" ") print() return def generate_powerset(items, subset_handler=tuple, verbose=False): """ Generate the powerset of an iterable `items`. Handling of the elements of the iterable is by whichever function is passed as `subset_handler`, which must be able to handle the `None` value for the empty set. The function `string_handler` will join the elements of the subset with the empty string (useful when `items` is an iterable of `str` variables). """ ps = {0: [subset_handler()]} n = len(items) p_dict = partitions_by_length(n-1, sorting=True, permuting=True) for p_len, parts in p_dict.items(): ps.setdefault(p_len, []) if p_len == 0: # singletons for offset in range(n): subset = subset_handler([items[offset]]) if verbose: if offset > 0: print(end=" ") if offset == n - 1: print(subset, end="\n") else: print(subset, end=",") ps.get(p_len).append(subset) for pcount, partition in enumerate(parts): distance = sum(partition) indices = (cumsum(partition)).tolist() for offset in range(n - distance): subset = subset_handler([items[offset]] + [items[offset:][i] for i in indices]) if verbose: if offset > 0: print(end=" ") if offset == n - distance - 1: print(subset, end="\n") else: print(subset, end=",") ps.get(p_len).append(subset) if verbose and p_len < n-1: print() return ps
Como ejemplo, escribí un programa de demostración CLI que toma una cadena como argumento de línea de comando:
⇣
a, b, c, d, e, f ab, bc, cd, de, ef ac, bd, ce, df ad, be, cf ae, bf af abc, bcd, cde, def abd, bce, cdf acd, bde, cef abe, bcf ade, bef ace, bdf abf aef acf adf abcd, bcde, cdef abce, bcdf abde, bcef acde, bdef abcf abef adef abdf acdf acef abcde, bcdef abcdf abcef abdef acdef abcdef
fuente
Si desea una longitud específica de subconjuntos, puede hacerlo así:
from itertools import combinations someSet = {0, 1, 2, 3} ([x for i in range(len(someSet)+1) for x in combinations(someSet,i)])
De manera más general, para los subconjuntos de longitud arbitraria, puede modificar el rango de rango. La salida es
[(), (0,), (1,), (2,), (3,), (0, 1), (0, 2), (0, 3), (1, 2), (1 , 3), (2, 3), (0, 1, 2), (0, 1, 3), (0, 2, 3), (1, 2, 3), (0, 1, 2, 3 )]
fuente
def powerset(some_set): res = [(a,b) for a in some_set for b in some_set] return res
fuente