我想找到没有空str的str的所有可能分区,并且必须包含ever char(不应包含原始str)
例如:
s = '1234'
partitions(s) # -> [['1', '2', '3', '4'], ['1', '2', '34'], ['1', '23', '4']
# ['12', '3', '4'], ['12', '34'], ['1', '234'], ['123', '4']]
# should not contain ['1234']
编辑:可以按任意顺序
为什么我的问题不重复:
我不希望这样的排列:
from itertools import permutations
s = '1234'
permutations(s) # returns ['1', '2', '3', '4'], ['1', '2', '4', '3']...
但是我想将字符串分成许多长度(请看一下第一个代码)
谢谢!
答案 0 :(得分:11)
您可以定义一个递归(生成器)函数。这个想法是:将所有长度的字符串的前缀与剩余字符串的所有分区组合在一起。
def partitions(s):
if len(s) > 0:
for i in range(1, len(s)+1):
first, rest = s[:i], s[i:]
for p in partitions(rest):
yield [first] + p
else:
yield []
partitions("1234")
的结果:
['1', '2', '3', '4']
['1', '2', '34']
['1', '23', '4']
['1', '234']
['12', '3', '4']
['12', '34']
['123', '4']
['1234']
请注意,该确实包含['1234']
,但此后可以轻松对其进行过滤,例如例如print([p for p in partitions("1234") if len(p) > 1])
,也可以将结果收集到list
,然后收集pop
最后一个元素。将其直接添加到递归函数将更加复杂,因为每个调用(但顶级调用 都应返回该“完整”分区)。
答案 1 :(得分:3)
一个想法可能如下。给定字符串“ 1234”,您可以对字符串进行分区以计算子字符串的位置。
import itertools
s="1234"
possibilities = []
for i in range(1,len(s)):
comb = itertools.combinations(range(1,len(s)), i)
possibilities+= [[s[0:c[0]]] + [s[c[i]:c[i+1]] for i in range(len(c)-1)] + [s[c[-1]:]] for c in comb]
输出
#[['1', '234'], ['12', '34'], ['123', '4'], ['1', '2', '34'], ['1', '23', '4'], ['12', '3', '4'], ['1', '2', '3', '4']]
此解决方案的输出中不包含['1234'](这是因为主循环从1开始而不是从0开始)。
只是一个脚注。
在不包括原始字符串的情况下对字符串进行分区的方法是
此解决方案所基于的想法是这样。根据上面的公式生成每个。该数字很大,并且不能存在多项式时间算法(至少您必须生成输出的每个元素,因此Ω(2^n)
是一般问题的下限)。
答案 2 :(得分:0)
使用this SO question中的代码列出所有子字符串(移植到python 3),然后删除主字符串。然后创建所有排列并仅过滤允许的排列。
import itertools
def get_all_substrings(input_string):
length = len(input_string)
return [input_string[i:j+1] for i in range(length) for j in range(i,length)]
def filter_func(string, iterable):
""" Leave only permutations that contain all letters from the string and have the same char count. """
all_chars = ''.join(iterable)
return True if len(all_chars) == len(string) and all(char in all_chars for char in string) else False
s = '1234'
partitions = get_all_substrings(s)
partitions.remove(s) # remove '1234' (results should be only substrings not equal to the original string)
results = []
# create all permutations of all substrings, for all sub-lengths of the string length (1, 2, 3...)
for i in range(len(s)):
permutations = list(itertools.permutations(partitions, i + 1))
accepted_permutations = tuple(filter(lambda p: filter_func(s, p), permutations)) # filter out unwanted permutations
results += accepted_permutations
res = list(set(tuple(sorted(l)) for l in results)) # filter out duplicates with different order
print(res)
这不像上面的递归解决方案那么好,但是我已经创建了,所以将其发布:D 编辑:完全重做了这个问题。