There must be a fast and efficient way to split a (text) string at the "nth" occurrence of a needle, but I cannot find it. There is a fairly full set of functions in the [strpos comments in the PHP manual](http://www.php.net/manual/en/function.strpos.php#102336), but that seems a bit much for what I need.

I have plain text as $string, and want to split it at *nth* occurrence of $needle, and in my case, needle is simply a space. (I can do the sanity checks!)

Can someone point me in the right direction? Many thanks!
Could be?

function split2($string,$needle,$nth){$max = strlen($string);$n = 0;
for($i=0;$i<$max;$i++){
if($string[$i]==$needle){$n++;
if($n>=$nth){
break;
}
}
}
$arr[] = substr($string,0,$i);$arr[] = substr($string,$i+1,$max); return$arr;
}
You can use recursion to do this too:


function strposn(string $haystack, string$needle, $nth,$offset = 0){ return $nth?strposn($haystack,$needle,$nth-1,strpos($haystack,$needle,$offset)+1):$offset; }

$my_string = 'one two three four five six';$split_pos = strposn($my_string,' ',4); echo 'left: "'.substr($my_string,0,$split_pos-1).'"'.PHP_EOL; echo 'right: "'.substr($my_string,$split_pos).'"'.PHP_EOL;  produces: none left: "one two three four" right: "five six"  If you care what happens when passing in either 0 or a number higher than the actual number of occurrences you may need to add some checking. I really like Hamze GhaemPanah's [answer] for its brevity. However, there's a small bug in it. In the original code: $i = $pos = 0; do {$pos = strpos( $string,$needle, $pos+1 ); } while($i++ < $nth);  $nth in the do while loop should be replaced with ($nth-1) as it will incorrectly iterate one extra time - setting the $pos to the position of the $nth+1 instance of the needle. Here's an example [playground to demonstrate]. If this link fails here is the code: $nth = 2;
$string = "44 E conway ave west horse";$needle = " ";

echo"======= ORIGINAL =======\n";

$i =$pos = 0;
do {
$pos = strpos($string, $needle,$pos+1 );
} while( $i++ <$nth);

echo "position: $pos \n"; echo substr($string, 0, $pos) . "\n\n"; /* Outputs: ======= ORIGINAL ======= position: 11 44 E conway */ echo"======= FIXED =======\n";$i = $pos = 0; do {$pos = strpos( $string,$needle, $pos+1 ); } while($i++ < ($nth-1) ); echo "position:$pos \n";
echo substr($string, 0,$pos);

/*
Outputs:

======= FIXED =======
position: 4
44 E

*/


That is, when searching for the position of the 2nd instance of our needle, our loop iterates one extra time setting $pos to the position of our 3rd instance of our needle. So, when we split the string on the 2nd instance of our needle - as the OP asked - we get the incorrect substring. Kudos to Hamze for the clever answer. : /php?q=1071#a1290 : https://www.tehplayground.com/vAutCoJvXvqRBWAu Easily, just do it: (updated!)$i = $pos = 0; do {$pos = strpos( $string,$needle, $pos+1 ); } while( ++$i < $nth); If your needle will always be 1 character, use Galled's answer, it's going to be faster by quite a bit. If your$needle is a string, try this.  Seems to work fine.

function splitn($string,$needle, $offset) {$newString = $string;$totalPos = 0;
$length = strlen($needle);
for($i = 0;$i < $offset;$i++)
{
$pos = strpos($newString, $needle); // If you run out of string before you find all your needles if($pos === false)
return false;
$newString = substr($newString, $pos+$length);
$totalPos +=$pos+$length; } return array(substr($string, 0, $totalPos-$length),substr($string,$totalPos));
}
Taking [Matthew's answer] and adding a solution for [Dɑvïd's comment]:

function split_nth($str,$delim, $n) {$result = array_map(function($p) use ($delim) {
return implode($delim,$p);
}, array_chunk(explode($delim,$str), $n));$result_before_split = array_shift($result);$result_after_split = implode(" ", $result); return array($result_before_split, $result_after_split); } Just call it by: list($split_before, \$split_after) = split_nth("1 2 3 4 5 6", " ", 2);

Output:

1 2
3 4 5 6

: https://stackoverflow.com/a/5956463/4829915
: https://stackoverflow.com/questions/5956066/how-to-split-a-string-in-php-at-nth-occurrence-of-needle/5956463#comment6869588_5956463