Я с радостью предоставлю вам совершенно другой подход к генерации желаемых данных очень прямым способом. ( Демонстрация того, что последует )
var_export(preg_match_all('/ |$/','I am John',$out,PREG_OFFSET_CAPTURE)?array_column($out[0],1):'failure');
Выход:
array (
0 => 1,
1 => 4,
2 => 9,
)
Определение длины каждой подстроки с приращением слова фактически совпадает с определением offset
каждого завершающего пробела, или по последнему слову - полной длины строки.
preg_match_all () имеет встроенный «флаг» для этого: PREG_OFFSET_CAPTURE
preg_match_all()
до того, как любая манипуляция с массивом выведет это:
array (
0 =>
array (
0 =>
array (
0 => ' ', // <-- the space after 'I' matched by ' '
1 => 1,
),
1 =>
array (
0 => ' ', // <-- the space after 'am' matched by ' '
1 => 4,
),
2 =>
array (
0 => '', // <-- the end of the string (after 'John') matched by '$'
1 => 9,
),
),
)
array_column()
используется в $out[0]
для извлечения только значений смещения (исключая бесполезные пустые и пустые строки).
Вот еще один, совершенно другой метод:
array_reduce(preg_split('/(?= )/',$string),function($carry,$item){echo $carry+=strlen($item)," "; return $carry;},0);
output: 1 4 9
Это разбивает строку на строку "нулевой ширины", за которой следует пробел. Это означает, что в процессе взрыва пробелы не теряются - это сохраняет длину строки и подстроки для простого добавления.