Splitting strings in PHP and get the last part

PhpString

Php 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 pattern
  • explode($pattern,$string) split strings within a given pattern
  • end($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.

3v4l link

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

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionRaphael JegerView Question on Stackoverflow
Solution 1 - PhpWesley Schleumer de GóesView Answer on Stackoverflow
Solution 2 - PhpDaleView Answer on Stackoverflow
Solution 3 - PhpGrant ThomasView Answer on Stackoverflow
Solution 4 - PhpLuke BaulchView Answer on Stackoverflow
Solution 5 - PhpInfinityView Answer on Stackoverflow
Solution 6 - PhpkenorbView Answer on Stackoverflow
Solution 7 - Phprybo111View Answer on Stackoverflow
Solution 8 - Phprybo111View Answer on Stackoverflow
Solution 9 - PhpMd. Zahangir AlamView Answer on Stackoverflow
Solution 10 - Phplive627View Answer on Stackoverflow
Solution 11 - PhpEnricoView Answer on Stackoverflow
Solution 12 - PhpNik DrosakisView Answer on Stackoverflow
Solution 13 - PhpNelsonView Answer on Stackoverflow
Solution 14 - PhpAliView Answer on Stackoverflow
Solution 15 - PhpGilbert ArafatView Answer on Stackoverflow