Учитывая набор
{0, 1, 2, 3}
Как я могу произвести подмножества:
[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}]
Ответы:
На itertools
странице Python есть точный powerset
рецепт для этого:
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))
Выход:
>>> 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')]
Если вам не нравится этот пустой кортеж в начале, вы можете просто изменить range
оператор, range(1, len(s)+1)
чтобы избежать комбинации нулевой длины.
s = list(iterable)
нужен?
__len__
реализации; попробуйте powerset((n for n in range(3)))
без переноса списка.
powerset(range(3))
будет нормально работать даже безs = list(iterable)
.
Вот еще код для набора мощности. Это написано с нуля:
>>> 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]
Комментарий Марка Рушакова применим здесь: «Если вам не нравится этот пустой кортеж в начале, on.», Вы можете просто изменить оператор диапазона на range (1, len (s) +1), чтобы избежать комбинации длины 0 ", за исключением моего случая, когда вы меняете for i in range(1 << x)
на for i in range(1, 1 << x)
.
Возвращаясь к этому годы спустя, я бы теперь написал это так:
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]
И тогда тестовый код будет выглядеть так, скажем:
print(list(powerset([4, 5, 6])))
Использование yield
означает, что вам не нужно вычислять все результаты в одном фрагменте памяти. Предполагается, что предварительный расчет масок вне основного цикла является стоящей оптимизацией.
Если вы ищете быстрый ответ, я просто искал "python power set" в Google и нашел следующее: Python Power Set Generator
Вот копия кода с этой страницы:
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
Это можно использовать так:
l = [1, 2, 3, 4]
r = [x for x in powerset(l)]
Теперь r - это список всех нужных вам элементов, который можно отсортировать и распечатать:
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]]
[[][]]
, чтобы исправить , что только отдельные случаи для проверки длиныif len(seq) == 0: yield [] elif len(seq) == 1: yield seq yield []
Я знаю, что ранее уже добавлял ответ, но мне очень нравится моя новая реализация. Я беру набор в качестве ввода, но на самом деле он может быть любым итеративным, и я возвращаю набор наборов, который является набором мощности ввода. Мне нравится этот подход, потому что он больше соответствует математическому определению набора мощности ( набора всех подмножеств ).
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
Если вам нужен именно тот результат, который вы опубликовали в своем ответе, используйте это:
>>> [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}]
Известно, что количество элементов силового набора такое 2 ** len(A)
, чтобы хорошо было видно в for
контуре.
Мне нужно преобразовать входные данные (в идеале набор) в список, потому что набор представляет собой структуру данных из уникальных неупорядоченных элементов, и порядок будет иметь решающее значение для создания подмножеств.
selector
является ключевым в этом алгоритме. Обратите внимание, что он selector
имеет ту же длину, что и входной набор, и для этого используется f-строка с отступом. По сути, это позволяет мне выбирать элементы, которые будут добавляться к каждому подмножеству во время каждой итерации. Скажем, входной набор состоит из 3 элементов {0, 1, 2}
, поэтому селектор будет принимать значения от 0 до 7 (включительно), которые в двоичном формате:
000 # 0
001 # 1
010 # 2
011 # 3
100 # 4
101 # 5
110 # 6
111 # 7
Таким образом, каждый бит может служить индикатором того, нужно ли добавлять элемент исходного набора или нет. Посмотрите на двоичные числа и просто подумайте о каждом числе как об элементе супернабора, что 1
означает, что j
должен быть добавлен элемент по индексу , и 0
означает, что этот элемент не следует добавлять.
Я использую понимание набора для создания подмножества на каждой итерации, и я конвертирую это подмножество в, frozenset
чтобы добавить его вps
(набор мощности). В противном случае я не смогу добавить его, потому что набор в Python состоит только из неизменяемых объектов.
Вы можете упростить код, используя некоторые понимания Python, чтобы избавиться от этих циклов for. Вы также можете использовать, zip
чтобы избежать использования j
индекса, и код будет следующим:
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)
}
Вот и все. Что мне нравится в этом алгоритме, так это то, что он более ясный и интуитивно понятный, чем другие, потому что он выглядит волшебно, на что можно положиться, itertools
даже если он работает так, как ожидалось.
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
Например:
get_power_set([1,2,3])
Уступать
[[], [1], [2], [1, 2], [3], [1, 3], [2, 3], [1, 2, 3]]
power_set
) в цикле, которым она управляет, - очень сомнительная практика. Например, предположим , что вы написали это вместо предложенной переменной модифицирующие кода: power_set += [list(sub_set)+[elem]]
. Тогда цикл не прекращается.
Я нашел следующий алгоритм очень понятным и простым:
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
Другой способ создания набора мощности - создание всех двоичных чисел, имеющих n
биты. В качестве степенного набора количество n
цифр равно 2 ^ n
. Принцип этого алгоритма состоит в том, что элемент может присутствовать или не присутствовать в подмножестве, поскольку двоичная цифра может быть единицей или нулем, но не обоими сразу.
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
Я нашел оба алгоритма, когда проходил MITx: 6.00.2x Introduction to Computational Thinking and Data Science, и считаю, что это один из самых простых для понимания алгоритмов, которые я видел.
Я просто хотел предложить наиболее понятное решение - версию против кодового гольфа.
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
Результаты, достижения
Все наборы длины 0
[()]
Все наборы длины 1
[('x',), ('y',), ('z',)]
Все наборы длины 2
[('x', 'y'), ('x', 'z'), ('y', 'z')]
Все наборы длины 3
[('x', 'y', 'z')]
Для получения дополнительной информации см. Документацию itertools , а также статью в Википедии о наборах мощности
Просто быстрое освежение питания!
Набор мощности набора X - это просто набор всех подмножеств X, включая пустой набор
Пример набора X = (a, b, c)
Набор мощности = {{a, b, c}, {a, b}, {a, c}, {b, c}, {a}, {b}, {c}, {}}
Вот еще один способ найти набор мощности:
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]))
полный кредит на источник
Это можно сделать очень естественно с помощью 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}
Простым способом было бы использовать внутреннее представление целых чисел в арифметике с дополнением до 2.
Двоичное представление целых чисел выглядит как {000, 001, 010, 011, 100, 101, 110, 111} для чисел в диапазоне от 0 до 7. Для целочисленного значения счетчика, считая 1 включением соответствующего элемента в коллекцию и '0' в качестве исключения мы можем создавать подмножества на основе последовательности подсчета. Числа должны быть сгенерированы от 0
до, pow(2,n) -1
где n - длина массива, то есть количество битов в двоичном представлении.
Простую функцию генератора подмножеств, основанную на ней, можно записать, как показано ниже. Это в основном полагается
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
а затем его можно использовать как
def get_subsets(array):
powerset = []
for i in subsets(array):
powerser.append(i)
return powerset
Тестирование
Добавление следующего в локальный файл
if __name__ == '__main__':
sample = ['b', 'd', 'f']
for i in range(len(sample)):
print "Subsets for " , sample[i:], " are ", get_subsets(sample[i:])
дает следующий вывод
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']]
С пустым набором, который является частью всех подмножеств, вы можете использовать:
def subsets(iterable):
for n in range(len(iterable) + 1):
yield from combinations(iterable, n)
Почти во всех этих ответах используется list
вместо set
, что для меня показалось немного читерским. Итак, из любопытства я попытался сделать простую версию действительно наset
и обобщить для других "новичков в Python".
Я обнаружил, что при работе с реализацией набора Python есть пара странностей . Основным сюрпризом для меня стало обращение с пустыми наборами. Это контрастирует с реализацией Ruby Set , где я могу просто сделать Set[Set[]]
и получить Set
один пустой Set
, поэтому сначала я нашел это немного запутанным.
Для обзора, работая powerset
с set
s, я столкнулся с двумя проблемами:
set()
принимает итерацию, поэтому set(set())
вернется, set()
потому что итерируемый пустой набор пуст (да, я думаю :))set({set()})
и set.add(set)
не будет работать, потому что set()
не хешируетсяЧтобы решить обе проблемы, я использовал frozenset()
, что означает, что я не совсем получаю то, что хочу (буквально шрифт set
), но использую общее set
взаимодействие.
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
Ниже мы получаем frozenset
правильные 2² (16) с на выходе:
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})}
Поскольку в Python нет возможности иметь a set
of set
s, если вы хотите превратить эти frozenset
s в set
s, вам придется отобразить их обратно в list
( list(map(set, powerset(set([1,2,3,4]))))
) или изменить приведенное выше.
Возможно, вопрос устаревает, но я надеюсь, что мой код кому-то поможет.
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
Используйте функцию powerset()
из пакета more_itertools
.
Дает все возможные подмножества итерируемого
>>> list(powerset([1, 2, 3]))
[(), (1,), (2,), (3,), (1, 2), (1, 3), (2, 3), (1, 2, 3)]
Если вам нужны наборы, используйте:
list(map(set, powerset(iterable)))
Получение всех подмножеств с помощью рекурсии. Сумасшедший однострочный
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 [[]]
На основе решения Haskell
subsets :: [a] -> [[a]]
subsets [] = [[]]
subsets (x:xs) = map (x:) (subsets xs) ++ subsets xs
NameError: name 'List' is not defined
List
импорт
def 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
Сделать это можно так:
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]))
Выход:
[[], [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]]
Это дико, потому что ни один из этих ответов на самом деле не возвращает фактический набор Python. Вот запутанная реализация, которая даст набор мощности, который на самом деле является 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([]) ])
Однако мне бы хотелось увидеть лучшую реализацию.
[*map(set, chain.from_iterable(combinations(s, r) for r in range(len(s)+1)))]
; функция arg of map
может быть, frozenset
если хотите.
Вот моя быстрая реализация с использованием комбинаций, но с использованием только встроенных модулей.
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
Все подмножества в диапазоне n установлены:
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 "{}")
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)
Вариант вопроса - это упражнение, которое я вижу в книге «Открытие компьютерных наук: междисциплинарные проблемы, принципы и программирование на Python. Издание 2015 года». В этом упражнении 10.2.11 входом является просто целое число, а выходом должны быть наборы мощности. Вот мое рекурсивное решение (не использующее ничего, кроме базового python3)
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))
И на выходе
[[], [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]] Количество подсписки: 16
Я не сталкивался с этой more_itertools.powerset
функцией и рекомендую ее использовать. Я также рекомендую не использовать порядок вывода по умолчанию itertools.combinations
, часто вместо этого вы хотите минимизировать расстояние между позициями и отсортировать подмножества элементов с меньшим расстоянием между ними выше / перед элементами с большим расстоянием между ними.
На itertools
странице рецептов показано, что он используетchain.from_iterable
r
здесь соответствует стандартным обозначениям для нижней части биномиального коэффициента , s
обычно упоминается как n
в текстах по математике и на калькуляторах («n Выберите 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))
В других примерах здесь приводится набор мощности [1,2,3,4]
таким образом, что 2-кортежи перечислены в «лексикографическом» порядке (когда мы печатаем числа как целые числа). Если я напишу расстояние между числами рядом с ним (то есть разницу), это покажет мою точку зрения:
12 ⇒ 1
13 ⇒ 2
14 ⇒ 3
23 ⇒ 1
24 ⇒ 2
34 ⇒ 1
Правильный порядок подмножеств должен быть порядком, который сначала «исчерпывает» минимальное расстояние, например:
12 ⇒ 1
23 ⇒ 1
34 ⇒ 1
13 ⇒ 2
24 ⇒ 2
14 ⇒ 3
Использование чисел здесь делает этот порядок ["a","b","c","d"]
`` неправильным '', но рассмотрите, например, буквы, это более ясно, почему это может быть полезно для получения набора мощности в таком порядке:
ab ⇒ 1
bc ⇒ 1
cd ⇒ 1
ac ⇒ 2
bd ⇒ 2
ad ⇒ 3
Этот эффект более выражен с большим количеством элементов, и для моих целей он определяет разницу между осмысленным описанием диапазонов индексов набора мощности.
(О кодах Грея написано много и т. Д. О порядке вывода алгоритмов в комбинаторике, я не вижу в этом побочной проблемы).
На самом деле я просто написал довольно сложную программу, которая использует этот быстрый код целочисленного раздела для вывода значений в правильном порядке, но затем я обнаружил more_itertools.powerset
и для большинства применений, вероятно, нормально просто использовать эту функцию следующим образом:
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)
Я написал несколько более активных участие код , который будет печатать Powerset красиво (см репозитория для печати довольно функций я не включен здесь: print_partitions
, print_partitions_by_length
, и pprint_tuple
).
pset_partitions.py
Это все довольно просто, но все же может быть полезно, если вам нужен какой-то код, который позволит вам сразу получить доступ к различным уровням powerset:
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
В качестве примера я написал демонстрационную программу CLI, которая принимает строку в качестве аргумента командной строки:
python string_powerset.py abcdef
⇣
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
Если вам нужна определенная длина подмножеств, вы можете сделать это следующим образом:
from itertools import combinations
someSet = {0, 1, 2, 3}
([x for i in range(len(someSet)+1) for x in combinations(someSet,i)])
В более общем случае для подмножеств произвольной длины вы можете изменять диапазон диапазонов. На выходе
[(), (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) )]
def powerset(some_set):
res = [(a,b) for a in some_set for b in some_set]
return res