Вернуть все возможные комбинации строки при разбиении на n строк
Я сделал поиск по стеку потока по этому поводу, но не смог найти способ сделать это. Это, вероятно, связано с itertools.
Я хочу найти все возможные результаты разбиения строки, скажем строку thisisateststring
в n
(одинаковая или неравная длина, не имеет значения, оба должны быть включены) строки.
Например пусть n
быть 3
:
[["thisisat", "eststrin", "g"], ["th", "isisates", "tstring"], ............]
3 ответа
Включение пустых строк в ваши результаты будет довольно неловко с itertools.combinations()
, Вероятно, проще всего написать собственную рекурсивную версию:
def partitions(s, k):
if not k:
yield [s]
return
for i in range(len(s) + 1):
for tail in partitions(s[i:], k - 1):
yield [s[:i]] + tail
Это будет работать для любого номера k
желаемых разделов для любой строки s
,
Ты можешь использовать itertools.combinations
Вот. Вам просто нужно выбрать две точки разделения, чтобы сгенерировать каждую результирующую строку:
from itertools import combinations
s = "thisisateststring"
pools = range(1, len(s))
res = [[s[:p], s[p:q], s[q:]] for p, q in combinations(pools, 2)]
print res[0]
print res[-1]
Выход:
['t', 'h', 'isisateststring']
['thisisateststri', 'n', 'g']
Вот рецепт для разделения последовательности на n групп, основанный на коде Рэймонда Хеттингера:
import itertools as IT
def partition_into_n(iterable, n, chain=IT.chain, map=map):
"""
Based on http://code.activestate.com/recipes/576795/ (Raymond Hettinger)
Modified to include empty partitions, and restricted to partitions of length n
"""
s = iterable if hasattr(iterable, '__getslice__') else tuple(iterable)
m = len(s)
first, middle, last = [0], range(m + 1), [m]
getslice = s.__getslice__
return (map(getslice, chain(first, div), chain(div, last))
for div in IT.combinations_with_replacement(middle, n - 1))
In [149]: list(partition_into_n(s, 3))
Out[149]:
[['', '', 'thisisateststring'],
['', 't', 'hisisateststring'],
['', 'th', 'isisateststring'],
['', 'thi', 'sisateststring'],
...
['thisisateststrin', '', 'g'],
['thisisateststrin', 'g', ''],
['thisisateststring', '', '']]
Это медленнее, чем рекурсивное решение для малых n
,
def partitions_recursive(s, n):
if not n>1:
yield [s]
return
for i in range(len(s) + 1):
for tail in partitions_recursive(s[i:], n - 1):
yield [s[:i]] + tail
s = "thisisateststring"
In [150]: %timeit list(partition_into_n(s, 3))
1000 loops, best of 3: 354 µs per loop
In [151]: %timeit list(partitions_recursive(s, 3))
10000 loops, best of 3: 180 µs per loop
но, как и следовало ожидать, это быстрее для больших n
(по мере увеличения глубины рекурсии):
In [152]: %timeit list(partition_into_n(s, 10))
1 loops, best of 3: 9.2 s per loop
In [153]: %timeit list(partitions_recursive(s, 10))
1 loops, best of 3: 10.2 s per loop