简体   繁体   中英

Splitting strings in PHP and get the last part

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.

  • 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:

$strArray = explode('-',$str)
$lastElement = end(explode('-', $strArray));
// or
$lastElement = end(preg_split('/-/', $str));

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 '-'
$string = 'abc-123-xyz-789';
$exploded = explode('-', $string);
echo end($exploded);

This does not have the E_STRICT issue.

Just check whether or not the delimiting character exists, and either split or don't:

if (strpos($potentiallyDelimitedString, '-') !== FALSE) {
  found delimiter, so split
}

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).

This code will do that

<?php
$string = 'abc-123-xyz-789';
$output = explode("-",$string);
echo $output[count($output)-1];
?>

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.

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

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 = 'name@example.com';
$provider = explode('@', $email)[1];
echo $provider; // example.com

Or another way is list() :

$email = 'name@example.com';
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

只需调用以下单行代码:

 $expectedString = end(explode('-', $orignalString));

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

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 .

对我来说最核心的方式:

  $last = explode('-',$urlId)[count(explode('-',$urlId))-1];
array_reverse(explode('-', $str))[0]

You can do it like this:

$str = "abc-123-xyz-789";
$last = array_pop( explode('-', $str) );
echo $last; //echoes 789

You can use array_pop combined with explode

Code:

$string = 'abc-123-xyz-789';
$output = array_pop(explode("-",$string));
echo $output;

DEMO : Click here

You can do it like this:

$str = "abc-123-xyz-789";
$arr = explode('-', $str);
$last = array_pop( $arr );
echo $last; //echoes 789

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM