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
Easily, just do it:
$i = $pos = 0;
do {
$pos = strpos($string, $needle, $pos+1);
} while(++$i < $nth);
function split_nth($haystack, $needle, $nth){
$result = array();
if(substr_count($haystack,$needle) > ($nth-1)){
$haystack = explode($needle, $haystack);
$result[] = implode(array_splice($haystack, 0, $nth), $needle);
$result[] = implode($haystack, $needle);
}
return $result;
}
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
function strposnth($haystack,$needle,$n){
$offset = 0;
for($i=1;$i<=$n;$i++){
$indx = strpos($haystack, $needle, $offset);
if($i == $n || $indx === false)
return $indx;
else {
$offset = $indx+1;
}
}
return false;
}
It 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 something like the following:
/* Function copied from the PHP manual comment you referenced */
function strnripos_generic( $haystack, $needle, $nth, $offset, $insensitive, $reverse )
{
// If needle is not a string, it is converted to an integer and applied as the ordinal value of a character.
if(! is_string($needle)) {
$needle = chr((int)$needle);
}
// Are the supplied values valid / reasonable?
$len = strlen($needle);
if(1 > $nth || 0 === $len) {
return false;
}
if($insensitive) {
$haystack = strtolower($haystack);
$needle = strtolower($needle );
}
if($reverse) {
$haystack = strrev($haystack);
$needle = strrev($needle );
}
// $offset is incremented in the call to strpos, so make sure that the first
// call starts at the right position by initially decreasing $offset by $len.
$offset -= $len;
do
{
$offset = strpos($haystack, $needle, $offset + $len);
} while(--$nth && false !== $offset);
return false === $offset || ! $reverse ? $offset : strlen($haystack) - $offset;
}
// Our split function
function mysplit ($haystack, $needle, $nth) {
$position = strnripos_generic($haystack, $needle, $nth, 0, false, false);
$retval = array();
if ($position !== false) {
$retval[0] = substr($haystack, 0, $position-1);
$retval[1] = substr($haystack, $position);
return $retval;
}
return false;
}
Then you just use the mysplit function, and you'll get an array with two substrings. First containing all characters up to the nth occurrence of the needle (not included), and second from the nth occurrence of the needle (included) to the end.