获取任何长度的所有可能的str分区

时间:2018-09-04 13:20:50

标签: python arrays string python-3.x

我想找到没有空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']...

但是我想将字符串分成许多长度(请看一下第一个代码)

谢谢!

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开始)。

只是一个脚注。
在不包括原始字符串的情况下对字符串进行分区的方法是

enter image description here

此解决方案所基于的想法是这样。根据上面的公式生成每个。该数字很大,并且不能存在多项式时间算法(至少您必须生成输出的每个元素,因此Ω(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 编辑:完全重做了这个问题。