Splitting strings in PHP and get the last part
PhpStringPhp Problem Overview
I need to split a string in PHP by "-" and get the last part.
So from this:
> abc-123-xyz-789
I expect to get
> "789"
This is the code I've come up with:
substr(strrchr($urlId, '-'), 1)
which works fine, except:
If my input string does not contain any "-", I must get the whole string, like from:
> 123
I need to get back
> 123
and it needs to be as fast as possible.
Php Solutions
Solution 1 - Php
split($pattern,$string)
split strings within a given pattern or regex (it's deprecated since 5.3.0)preg_split($pattern,$string)
split strings within a given regex patternexplode($pattern,$string)
split strings within a given patternend($arr)
get last array element
So:
end(split('-',$str))
end(preg_split('/-/',$str))
$strArray = explode('-',$str)
$lastElement = end($strArray)
Will return the last element of a -
separated string.
And there's a hardcore way to do this:
$str = '1-2-3-4-5';
echo substr($str, strrpos($str, '-') + 1);
// | '--- get the last position of '-' and add 1(if don't substr will get '-' too)
// '----- get the last piece of string after the last occurrence of '-'
Solution 2 - Php
$string = 'abc-123-xyz-789';
$exploded = explode('-', $string);
echo end($exploded);
This does not have the E_STRICT issue.
Solution 3 - Php
Just check whether or not the delimiting character exists, and either split or don't:
if (strpos($potentiallyDelimitedString, '-') !== FALSE) {
found delimiter, so split
}
Solution 4 - Php
To satisfy the requirement that "it needs to be as fast as possible" I ran a benchmark against some possible solutions. Each solution had to satisfy this set of test cases.
$cases = [
'aaa-zzz' => 'zzz',
'zzz' => 'zzz',
'-zzz' => 'zzz',
'aaa-' => '',
'' => '',
'aaa-bbb-ccc-ddd-eee-fff-zzz' => 'zzz',
];
Here are the solutions:
function test_substr($str, $delimiter = '-') {
$idx = strrpos($str, $delimiter);
return $idx === false ? $str : substr($str, $idx + 1);
}
function test_end_index($str, $delimiter = '-') {
$arr = explode($delimiter, $str);
return $arr[count($arr) - 1];
}
function test_end_explode($str, $delimiter = '-') {
$arr = explode($delimiter, $str);
return end($arr);
}
function test_end_preg_split($str, $pattern = '/-/') {
$arr = preg_split($pattern, $str);
return end($arr);
}
Here are the results after each solution was run against the test cases 1,000,000 times:
test_substr : 1.706 sec
test_end_index : 2.131 sec +0.425 sec +25%
test_end_explode : 2.199 sec +0.493 sec +29%
test_end_preg_split : 2.775 sec +1.069 sec +63%
So turns out the fastest of these was using substr
with strpos
. Note that in this solution we must check strpos
for false
so we can return the full string (catering for the zzz
case).
Solution 5 - Php
This code will do that
<?php
$string = 'abc-123-xyz-789';
$output = explode("-",$string);
echo $output[count($output)-1];
?>
Solution 6 - Php
As per this post:
end((explode('-', $string)));
which won't cause an E_STRICT warning in PHP 5 (PHP magic). Although the warning will be issued in PHP 7, so adding @
in front of it can be used as a workaround.
Solution 7 - Php
As has been mentioned by others, if you don't assign the result of explode()
to a variable, you get the message:
> E_STRICT: Strict standards: Only variables should be passed by reference
The correct way is:
$words = explode('-', 'hello-world-123');
$id = array_pop($words); // 123
$slug = implode('-', $words); // hello-world
Solution 8 - Php
Since explode()
returns an array, you can add square brackets directly to the end of that function, if you happen to know the position of the last array item.
$email = '[email protected]';
$provider = explode('@', $email)[1];
echo $provider; // example.com
Or another way is list()
:
$email = '[email protected]';
list($prefix, $provider) = explode('@', $email);
echo $provider; // example.com
If you don't know the position:
$path = 'one/two/three/four';
$dirs = explode('/', $path);
$last_dir = $dirs[count($dirs) - 1];
echo $last_dir; // four
Solution 9 - Php
Just call the following single line of code:
$expectedString = end(explode('-', $orignalString));
Solution 10 - Php
The accepted answer has a bug in it where it still eats the first character of the input string if the delimiter is not found.
$str = '1-2-3-4-5';
echo substr($str, strrpos($str, '-') + 1);
Produces the expected result: 5
$str = '1-2-3-4-5';
echo substr($str, strrpos($str, ';') + 1);
Produces -2-3-4-5
$str = '1-2-3-4-5';
if (($pos = strrpos($str, ';')) !== false)
echo substr($str, $pos + 1);
else
echo $str;
Produces the whole string as desired.
Solution 11 - Php
This solution is null-safe and supports all PHP versions:
// https://www.php.net/manual/en/function.array-slice.php
$strLastStringToken = array_slice(explode('-',$str),-1,1)[0];
returning ''
if $str = null
.
Solution 12 - Php
The hardcore way for me:
$last = explode('-',$urlId)[count(explode('-',$urlId))-1];
Solution 13 - Php
You can do it like this:
$str = "abc-123-xyz-789";
$last = array_pop( explode('-', $str) );
echo $last; //echoes 789
Solution 14 - Php
You can use array_pop combined with explode
Code:
$string = 'abc-123-xyz-789';
$output = array_pop(explode("-",$string));
echo $output;
DEMO: Click here
Solution 15 - Php
You can do it like this:
$str = "abc-123-xyz-789";
$arr = explode('-', $str);
$last = array_pop( $arr );
echo $last; //echoes 789