Как разбить строку в PHP при появлении иглы? - PullRequest
21 голосов
/ 11 мая 2011

Должен быть быстрый и эффективный способ разбить (текстовую) строку при "n" появлении иглы, но я не могу ее найти. Существует довольно полный набор функций в комментариях strpos в руководстве по PHP , но это кажется немного большим для того, что мне нужно.

У меня есть простой текст как $string, и я хочу разделить его на nth вхождение $needle, и в моем случае needle это просто пробел. (Я могу сделать проверки здравомыслия!)

Может ли кто-нибудь указать мне правильное направление? Большое спасибо!

Ответы [ 9 ]

19 голосов
/ 11 мая 2011

Может быть?

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;
}
9 голосов
/ 11 мая 2011

Если ваша стрелка всегда будет 1 символом, воспользуйтесь ответом Галледа, она будет немного быстрее.Если ваш $ needle является строкой, попробуйте это.Кажется, работает нормально.

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));
}
8 голосов
/ 11 мая 2011

Лично я бы просто разбил его на массив с разнесением, а затем взорвал первые n-1 части как первую половину, а оставшуюся цифру взорвал как вторую половину.

5 голосов
/ 11 мая 2011

Вот подход, который я бы предпочел вместо решения регулярного выражения (см. Мой другой ответ):

function split_nth($str, $delim, $n)
{
  return array_map(function($p) use ($delim) {
      return implode($delim, $p);
  }, array_chunk(explode($delim, $str), $n));
}

Просто позвоните по телефону:

split_nth("1 2 3 4 5 6", " ", 2);

Выход:

array(3) {
  [0]=>
  string(3) "1 2"
  [1]=>
  string(3) "3 4"
  [2]=>
  string(3) "5 6"
}
1 голос
/ 04 января 2013

Я отредактировал функцию Галледа, чтобы она взрывалась после каждого n-го случая вместо первого.

function split2($string, $needle, $nth) {
  $max = strlen($string);
  $n = 0;
  $arr = array();
  //Loop trough each character
  for ($i = 0; $i < $max; $i++) {

    //if character == needle
    if ($string[$i] == $needle) {
      $n++;
      //Make a string for every n-th needle
      if ($n == $nth) {
        $arr[] = substr($string, $i-$nth, $i);
        $n=0; //reset n for next $nth
      }
      //Include last part of the string
      if(($i+$nth) >= $max) {
        $arr[] = substr($string, $i + 1, $max);
        break;
      }
    }
  }
  return $arr;
}
1 голос
/ 11 мая 2011

Это некрасиво, но, похоже, работает:

$foo = '1 2 3 4 5 6 7 8 9 10 11 12 13 14';

$parts = preg_split('!([^ ]* [^ ]* [^ ]*) !', $foo, -1,
            PREG_SPLIT_DELIM_CAPTURE | PREG_SPLIT_NO_EMPTY);

var_dump($parts);

Вывод:

array(5) {
  [0]=>
  string(5) "1 2 3"
  [1]=>
  string(5) "4 5 6"
  [2]=>
  string(5) "7 8 9"
  [3]=>
  string(8) "10 11 12"
  [4]=>
  string(5) "13 14"
}

Замените одиночные пробелы в запросе одним символом, который вы хотите разделить.Это выражение не будет работать как есть с несколькими символами в качестве разделителя.

Это жестко запрограммировано для каждого третьего пробела.С небольшой настройкой, вероятно, можно легко настроить.Хотя str_repeat для построения динамического выражения тоже подойдет.

1 голос
/ 11 мая 2011

Вы можете использовать что-то вроде следующего:

/* 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;
}

Тогда вы просто используете функцию mysplit, вы получите массив с двумя подстроками.Первый содержит все символы вплоть до n-го вхождения иглы (не включены), а второй - от n-го вхождения иглы (в комплекте) до конца.

0 голосов
/ 28 августа 2017
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;
}
0 голосов
/ 12 марта 2014
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;
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...