Как взорваться только на последнем встречающемся разделителе?

$split_point = ' - ';
$string = 'this is my - string - and more';

Как я могу сделать разделение, используя второй экземпляр $split_point, а не первый. Можно ли как-то указать поиск справа налево?

В основном, как я взрываюсь справа налево. Я хочу получить только последний экземпляр - .

Результат мне нужен:

$item[0]='this is my - string';
$item[1]='and more';

и не:

$item[0]='this is my';
$item[1]='string - and more';

person Codex73    schedule 04.04.2009    source источник


Ответы (13)


Вы можете использовать strrev, чтобы перевернуть строку, а затем перевернуть результаты обратно:

$split_point = ' - ';
$string = 'this is my - string - and more';

$result = array_map('strrev', explode($split_point, strrev($string)));

Хотя не уверен, что это лучшее решение.

person moff    schedule 04.04.2009
comment
не совсем понимаю использование array_map - person Codex73; 05.04.2009
comment
array_map запускает strrev для каждого элемента массива и возвращает результат. Вы также можете попробовать что-то вроде этого, что может быть проще: $result = array_reverse(explode($split_point, $string)); - person moff; 05.04.2009
comment
Это хорошее решение, относительно быстрое. Медленнее, чем взорваться, но быстрее, чем мое решение ниже. Я попробовал это в цикле for 1000 раз и получил 0,046875 с. - person John Boe; 19.10.2019

Как насчет этого:

$parts = explode($split_point, $string);
$last = array_pop($parts);
$item = array(implode($split_point, $parts), $last);

Не собираюсь выигрывать какие-либо награды в гольфе, но я думаю, что это показывает намерение и работает хорошо.

person Paolo Bergantino    schedule 04.04.2009
comment
Работает со строками utf-8 (например, арабский) - person perpetual_dream; 12.11.2012

Вот еще один способ сделать это:

$split_point = ' - ';
$string = 'this is my - string - and more';

$stringpos = strrpos($string, $split_point, -1);
$finalstr = substr($string,0,$stringpos);
person Basheer Ahmedu    schedule 20.04.2012

Если я правильно понимаю, вы хотите, чтобы примерный случай дал вам («это моя - строка», «и многое другое»)?

Встроенный split/explode, кажется, только для пересылки - вам, вероятно, придется реализовать его самостоятельно с помощью strrpos. (правый-левый поиск)

$idx = strrpos($string, $split_point);
$parts = array(substr($string, 0, $idx), substr($string, $idx+strlen($split_point)))
person v3.    schedule 04.04.2009

Почему бы не разделить на '-', а затем соединить первые две записи массива, которые вы получите вместе?

person Alister Bulman    schedule 04.04.2009
comment
но мне всегда нужно разделить последний экземпляр -. - person Codex73; 04.04.2009
comment
если он всегда будет последним экземпляром, вы можете найти последнее совпадение с помощью php.net/strrpos, затем в зависимости от того, с какой стороны вы хотите / из этой позиции с помощью substr - person Alister Bulman; 04.04.2009

Я наткнулся на то же самое и исправил это так:

$split_point = ' - ';
$string = 'this is my - string - and more';

$reverse_explode = array_reverse(explode($split_point, $string));
person Dennis    schedule 15.07.2011

Мне понравился ответ Моффа, но я улучшил его, ограничив количество элементов до 2 и перевернув массив:

$split_point = ' - ';
$string = 'this is my - string - and more';

$result = array_reverse(array_map('strrev', explode($split_point, strrev($string),2)));

Тогда $результат будет:

Array ( [0] => this is my - string [1] => and more )
person Coomie    schedule 09.07.2015

это моя - строка - и многое другое

  1. Используйте общую функцию разнесения, чтобы получить все строки
  2. Получить массив sizeof и выбрать последний элемент
  3. Извлечь последний элемент с помощью функции array_pop.
  4. Взорвите оставшуюся строку с тем же разделителем (если вы хотите, чтобы можно было использовать другой разделитель).

Код

$arrSpits=explode("", "this is my - string - and more");
$arrSize=count($arrSpits);

echo "Last string".$arrSpits[arrSize-1];//Output: and more


array_pop(arrSpits); //now pop the last element from array

$firstString=implode("-", arrSpits);
echo "First String".firstString; //Output: this is my - string
person Deepa MG    schedule 28.11.2017

Предполагая, что вы хотите игнорировать только первое вхождение $split_point, это должно сработать для вас:

# retrieve first $split_point position
$first = strpos($string, $split_point);
# retrieve second $split_point positon
$second = strpos($string, $split_point, $first+strlen($split_point));
# extract from the second $split_point onwards (with $split_point)
$substr = substr($string, $second);

# explode $substr, first element should be empty
$array = explode($split_point, $substr);

# set first element as beginning of string to the second $split_point
$array[0] = substr_replace($string, '', strpos($string, $substr));

Это позволит вам разделить каждое вхождение $split_point после (и включая) второго вхождения $split_point.

person quaff    schedule 05.04.2009

Просто идея:

function explode_reversed($delim,$s){
  $result = array();
  $w = "";
  $l = 0;
  for ($i = strlen($s)-1; $i>=0; $i-- ):
    if ( $s[$i] == "$delim" ):
      $l++;
      $w = "";
    else:
      $w = $s[$i].$w;
    endif;
    $result[$l] = $w;
  endfor;
return $result;
}
$arr = explode_reversed(" ","Hello! My name is John.");
print_r($arr);

Результат:

Array
(
    [0] => John.
    [1] => is
    [2] => name
    [3] => My
    [4] => Hello!
)

Но это гораздо медленнее, чем взорваться. Сделал тест:

$start_time = microtime(true);
for ($i=0; $i<1000;$i++)   
  $arr = explode_reversed(" ","Hello! My name is John.");
$time_elapsed_secs = microtime(true) - $start_time;
echo "time: $time_elapsed_secs s<br>";

Занимает 0,0625 - 0,078125 с

Но

for ($i=0; $i<1000;$i++)   
  $arr = explode(" ","Hello! My name is John.");

Занимает всего 0,015625 с

Похоже, самое быстрое решение:

array_reverse(explode($your_delimiter, $your_string));

В цикле 1000 раз это лучшее время, которое я могу получить 0,03125 с.

person John Boe    schedule 19.10.2019

Не знаю, почему никто не опубликовал работающую функцию с поддержкой $limit, но это для тех, кто знает, что они будут часто ее использовать:

<?php
function explode_right($boundary, $string, $limit)
{
 return array_reverse(array_map('strrev', explode(strrev($boundary), strrev($string), $limit)));
}

$string = 'apple1orange1banana1cupuacu1cherimoya1mangosteen1durian';
echo $string.'<br /><pre>'.print_r(explode_right(1, $string, 3),1).'</pre>';
?>
person John    schedule 22.12.2020

Я не в восторге от всех чрезмерно спроектированных ответов, которые вызывают множество функций и / или повторяют данные несколько раз. Все эти функции реверсирования строк и массивов делают технику очень трудной для понимания.

Regex в этом случае очень элегантен. Именно так я бы сделал это в профессиональном приложении:

Код: (Демо)

$string = 'this is my - string - and more';
var_export(preg_split('~.*\K - ~', $string));

Выход:

array (
  0 => 'this is my - string',
  1 => 'and more',
)

Жадно сопоставляя символы (.*), затем перезапуская полное сопоставление строки (\K), затем сопоставляя последнюю встречающуюся разделяющую подстроку (-), вы можете быть уверены, что отделите только последнюю подстроку от строки.

person mickmackusa    schedule 10.03.2021

$split_point = ' - ';
$string = 'this is my - string - and more';
$result = end(explode($split_point, $string));

Это работает нормально

person Community    schedule 21.11.2014