Ну, нет необходимости делать петли. Если мы хотим разбить строку s
на m
подстроки длиной k
каждая, эта проблема эквивалентна выборке m+1
интервалов между подстроками с общей длиной, равной len (s) -m * k.
Существует довольно хорошее дискретное распределение со свойством, что выборочные значения суммируются до фиксированного количества - Многочленное распределение . Расщепление строки по интервалам тогда довольно тривиально, возможно, можно оптимизировать
Код, Python 3.7.5 Anaconda x64, Win10.
import numpy as np
from typing import List
LoS = List[str]
def string2substrings(s: str, m:int, k: int) -> LoS:
"""
split string s into m substrings with length k each
"""
l = len(s)
if l == 0:
raise RuntimeError(f"Empty input string")
if k <= 0:
raise RuntimeError(f"Bad substrung length {k}")
if m <= 0:
raise RuntimeError(f"Bad substrung count {m}")
if l < m*k:
raise RuntimeError(f"cannot split string {s} into {m} pieces with length {k} - source length {l} is too short")
if l == m*k: # trivial case of all zero intervals
rv = [s[t*k:t*k+k] for t in range(0, m)]
return rv
# we will sample m+1 intervals which sum to l-m*k
# for that we will use multinomial distribution which
# sums to fixed value by itself
p = np.full(m+1, 1.0/np.float64(m+1), dtype=np.float64) # equal m+1 probabilities
intervals = np.random.multinomial(n = l - m*k, pvals = p)
print((intervals, np.sum(intervals)))
rv = list()
end = 0
for count, i in enumerate(intervals):
if count == m:
break
start = end+i
end = start + k
rv.append(s[start:end])
return rv
print(string2substrings("qwertyuiopas", 3, 3))