Split words that are too big I need to optimize the below code, as much as possible in:


using less resources as possible
being as fast as possible


What the code does is simple, it splits the string by words and only if a word is equal or bigger than 40 characters it will add spaces every X characters to the word that was too big:

&lt;?php

$text = "more text here 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000.1% more text here!";

foreach (explode(" ", $text) as $word)
{
    if (strlen($word) &gt;= 40)
    {
        $word = wordwrap($word, 8, " ", true);
    }
    $result[] = $word;
}
$data = implode(" ", $result);
echo $data;


Live DEMO

Is there anything that could be improved in this already simple code?
I would think a better approach might be to identify location of spaces in string and look for cases where there is index position > 40 between these spaces, and then to insert the space into the string as necessary.

This would certainly be a memory-optimized way of working with this as you could potentially only need to hold the subject string (with any inserted separators) in memory, along with a few helper variables.

Your current approach would hold all the following in memory:


$text - the main subject string
temporary storage of explode results
$word - a substring duplication of content already stored in $text)
$result - an array containing duplicated content from $text + inserts
$data - a duplicate copy of content in $result just joined into a string on the separator.


So, there is a lot of duplication of storage in your solution.

I am guessing there is also increased operational complexity around the explode() and implode() operations that could be avoided.

I would also consider generalizing this into a function.  I have given some sample code below for how this might look:

function chunk_substring(
    $subject_string,
    $separator = ' ',
    $max_substring_length = 40,
    $chunk_size = 8
) {
    // not shown - validate input as non-zero length strings or positive integers
    // as appropriate. May also want to check logic around chunk size
    // needing to be less than max substring length and such

    // loop through index positions of separator in target string
    $previous_index = 0;
    $continue = true;
    $separator_length = strlen($separator);
    while ($continue) {
        $next_index = strpos($subject_string, $separator, $previous_index);
        if($next_index === false) {
            // separator not found in remainder of string
            $continue = false;
            continue;
        }
        if($next_index === $previous_index) {
            // we had a separator match at beginning of string
            // or consecutive separators
            // let's increment $previous_index by separator length
            $previous_index += $separator_length ;
            continue;
        }
        if(($next_index - $previous_index) &gt;= $max_substring_length) {
            // we have a "long" substring
            // let's start inserting separators into it
            $idx = $previous_index + $chunk_size;          
            while ($idx &lt; $next_index) {
                // insert $separator at $idx
                $subject_string = substr_replace(
                    $subject_string,
                    $separator,
                    $idx,
                    0
                );

                // update $next_index to account for length of newly added
                // segment to string
                $next_index += $separator_length;

                // increase $idx by $chunk_size + $separator_length
                $idx = $idx + $chunk_size + $separator_length;
            }
        }
        // We are done evaluating / modifying this string segment
        // Set $previous_index to $next_index value in preparation for
        // next iteration
        $previous_index = $next_index;              
    }

    // return the string
    return $subject_string;
}


This approach would hold the following in memory:


$subject_string - would potentially grow as separators are inserted. You could also potentially have the function pass this by reference if you desire to have this function directly modify the external variable that is passed in
$separator - small string
Various low memory footprint integer variables for configuration and index storage.


Much less duplication in memory in this case to where overall memory utilization would scale (more or less) 1:1 with size of input string.

You might take a look at the accepted answer for the StackOverflow post I have linked below which deals with the related question of using explode() vs. string tokenization, which is, in essence, what I am proposing.  You might consider running a similar test to find out for your self what works best for your use cases.

https://stackoverflow.com/questions/5861826/exploding-an-array-within-a-foreach-loop-parameter