Create a 2-element array by exploding only on the last occurring delimiter
Asked Answered
P

13

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

How can I make a split using the second instance of $split_point and not the first one. Can I specify somehow a right to left search?

Basically how do I explode from right to left. I want to pick up only the last instance of " - ".

Result I need:

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

and not:

$item[0] = 'this is my';
$item[1] = 'string - and more';
Pedantry answered 4/4, 2009 at 16:18 Comment(0)
B
33

You may use strrev to reverse the string, and then reverse the results back:

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

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

Not sure if this is the best solution though.

Actual output: (Demo)

array (
  0 => 'and more',
  1 => 'string',
  2 => 'this is my',
)
Byelostok answered 4/4, 2009 at 16:25 Comment(3)
dont quite also get the array_map usagePedantry
array_map runs strrev over every element in the array, and returns the result. You may also try something like this, which may be simpler: $result = array_reverse(explode($split_point, $string));Byelostok
This is good solution, relatively fast. Slower than explode but faster than my solution bellow. I tried this in a for loop of 1000 times and got 0.046875s.Gaucho
T
14

How about this:

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

Not going to win any golf awards, but it shows intent and works well, I think.

Thylacine answered 4/4, 2009 at 16:49 Comment(1)
Works with utf-8 strings (ex: Arabic)Arnitaarno
P
9

Here is another way of doing it:

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

$stringpos = strrpos($string, $split_point, -1);
$finalstr = substr($string,0,$stringpos);
Propriety answered 20/4, 2012 at 9:12 Comment(1)
This answer doesn't even attempt to produce the required 2-element array. This answer is not safe to call if it is possible that the input string will not contain the $split_point string.Burdick
B
5

If I understand correctly, you want the example case to give you ('this is my - string', 'and more')?

Built-in split/explode seems to be forwards-only - you'll probably have to implement it yourself with strrpos. (right-left search)

$idx = strrpos($string, $split_point);
$parts = array(substr($string, 0, $idx), substr($string, $idx+strlen($split_point)))
Buoyancy answered 4/4, 2009 at 16:25 Comment(1)
I wouldn't trust this snippet because it is not checking if $idx is false.Burdick
B
3

I am underwhelmed by all of the over-engineered answers which are calling many functions and/or iterating over data multiple times. All of those string and array reversing functions make the technique very hard to comprehend.

Regex is powerfully elegant in this case. This is exactly how I would do it in a professional application:

Code: (Demo)

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

Output:

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

By greedily matching characters (.*), then restarting the fullstring match (\K), then matching the last occurring delimiting substring (" - "), you are assured to only separate the final substring from the string.

p.s. This solution will return the whole input string as a single-element array if there are no delimiting strings (" - ") found in the input string.

Burdick answered 10/3, 2021 at 14:5 Comment(3)
unreadable is not powerfully elegantEhr
I find this 7-character pattern in a single function approach to be very elegant. If you don't know what *, \K, and " - " do, then my answer explains these basic subpatterns.Burdick
I agree this is a good use case for regex, and is far cleaner than the horrible approaches of operating on strings using convoluted combinations of array functions. People are afraid of regex, and it is indeed sometimes incredibly unreadable, but in this case it's short, simple, and works perfectly.Coenocyte
S
2

Why not split on ' - ', but then join the first two array entries that you get back together?

Siret answered 4/4, 2009 at 16:33 Comment(3)
but i need to split on the last instance always of -.Pedantry
if it is always going to be the last instance, you can find the last match with php.net/strrpos, then that whichever side you want to/from that position with substrSiret
If you have a question to ask the asker, you can use a comment instead of posting a question as an answer.Burdick
B
1

I liked Moff's answer, but I improved it by limiting the number of elements to 2 and re-reversing the array:

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

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

Then $result will be :

Array ( [0] => this is my - string [1] => and more )
Biddy answered 9/7, 2015 at 8:4 Comment(0)
S
0

Assuming you only want the first occurrence of $split_point to be ignored, this should work for you:

# 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));

This will allow you to split on every occurrence of $split_point after (and including) the second occurrence of $split_point.

Surrey answered 5/4, 2009 at 20:28 Comment(1)
I wouldn't trust this snippet because it does not check if strpos() returned false.Burdick
H
0

this is my - string - and more

  1. Use common explode function to get all strings
  2. Get sizeof array and fetch last item
  3. Pop last item using array_pop function.
  4. Implode remaining string with same delimeter(if u want other delimeter can use).

Code

$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
Hanan answered 28/11, 2017 at 7:40 Comment(2)
Why is this answer exploding on a zero-width delimiter?Burdick
This answer is riddled with typos, will not work, and should be removed from the page.Burdick
P
0

Not sure why no one posted a working function with $limit support though here it is for those who know that they'll be using this frequently:

<?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>';
?>
Proclivity answered 22/12, 2020 at 5:4 Comment(1)
Coomie's answer from 2015 DOES show how to implement an explosion limit.Burdick
D
0

I am missing the point of using explosives in such a peaceful situation: we always need two-element array as a result:

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

$result = [
substr($string, 0, strrpos($string, $split_point)),
substr($string, strrpos($string, $split_point) + strlen($split_point)),
];
var_export($result);

Output:

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

Duluth answered 31/7 at 12:42 Comment(1)
Is this 5-call solution safe to use if there are zero hyphens in the string? (Don't worry, know the answer)Burdick
S
-1
$split_point = ' - ';
$string = 'this is my - string - and more';
$result = end(explode($split_point, $string));

This is working fine

Secunderabad answered 21/11, 2014 at 9:10 Comment(1)
This unexplained answer does not fulfill the question requirements. This does not produce an array of 2 elements by splitting on the last occurring delimiter.Burdick
M
-1

The shortest path to your goal is:

1    $string = 'this is my - string - and more';
2    $res = explode(' - ', $string); //$res is now an array of three elements...
3    $last = end($str); //$last should now be: 'and more'

EXPLANATION

At the second line above, the explode() function had splitted your string using the ( ' - ' ) delimiter and stored the result into the $res variable, which is now an array contains three elements as follow:

 $res => [
    'this is my',
    'string',
    'and more'
    ]

At the third line, the end() function returned the last element of $res.

In general, your goal is made of two simple steps. And PHP does already provide several built-in functions to achieve each step like:

     'explode( )' //splits a string using a delimiter...

     'preg_split( )'; //splits a string usin a regex pattern.

     end( ) //returns the 'last' element of an array or 'false' if empty array.

     array_pop( ) //deletes the last element off an array AND returns it.

You could refer to the manual for each one of the above functions by clicking on its name. The manual shows detailed explanation and usage examples in various scenarios.

=========================================================

SOLUTION 2: Another path might be:

1    $string = 'this is my - string - and more';
2    $pos = strrpos($string, ' - ');
3    $str = substr($string, $pos + 3);

EXPLANATION:

At the second line above, the strrpos() function searches for the last occurrence of ( ' - ' ) inside our $string -this is what you want- and returns its position in relation to it; i.e.: start counting from the beginning of $string untill the last occurrence of ( ' - ' ). In our string above, if we count how many characters there are before the appearance of the last instance of ( ' - ' ), we will find them (18) characters, and this means the first character of ( ' - ' ) is located exactly at 19. Please, remember here that this is a zero-indexed counting; i.e.: we start counting from 0 not from 1, which means the the first character 't' is indexed at 0 not at 1, and the second 'h' is indexed at 1 not at 2... etc. etc.

At the third line, now that we know where to start splitting, we use the substr( ) function which does just that: it splits (extracts) a given string at a certain position. However, if we are to split the $string at 19 the result would be " - and more", because 19 is where the ( ' - ' ) starts. Hence we should take into account the length of ( ' - ' ) and add it to the $pos. In our case, the ( ' - ' ) is three-character length; and this is why I added (+3) to $pos in the code above. And by the way, if your $split_point is varying from task to task, you might want to store its length in another variable, let it be $len, for example. And our code would be:

1    $split_point = ' - '
2    $string = 'this is my - string - and more';
3    $pos = strrpos($string, $split_point);
4    $len = strlen($split_point);
5    $str = substr($string, $pos + $len);

Or.. for shorter code:

1    $split_point = ' - '
2    $string = 'this is my - string - and more';
3    $pos = strrpos($string, $split_point) + strlen($split_point);
4    $str = substr($string, $pos);

even shorter..

1    $split_point = ' - '
2    $string = 'this is my - string - and more';
3    $str = substr($string, strrpos($string, $split_point) + strlen($split_point));

In all these cases the $str variable should now be 'and more'; and you might want to trim the $srt using the trim() function as a final step.

strrpo( )

substr( )

strlen( )

trim( )

For your scenario, though, I find the end() function easier, more straight forward, and memorable. There's no need to re-invent the wheel.

Mcmanus answered 28/4 at 10:55 Comment(2)
I would not trust these approaches because they do not check if the returned value from strrpos() was false. Also "The shortest path to your goal is:" found in my answer.Burdick
The first snippet does not do what the question requires (splitting the string) -- $res = explode(' - ', $string); $last = end($str); only creates an array of all parts and $last is the last string of that array. Same problem with $pos = strrpos($string, ' - '); $str = substr($string, $pos + 3); -- your code doesn't do what is required.Burdick

© 2022 - 2024 — McMap. All rights reserved.