Native function to filter array by prefix

2.9k views Asked by At

Say I have an array with the following members:

car_porsche
car_mercedes
car_toyota
motorcycle_suzuki
motorcycle_honda
motorcycle_motoguzzi

How can I get an array with all the elements starting with car_? There was a native function for this but I forgot its name.

Do you know which function I mean? I know how to do it with for/foreach/array_filter. I'm quite sure there was a function for exactly this.

6

There are 6 answers

0
cletus On BEST ANSWER

Well, you could do it using preg_grep():

$output = preg_grep('!^car_!', $array);

You could use array_filter() too but you have to pass a test function into that.

0
mickmackusa On

Assuming that the search needle is a user-supplied value, before using it in a regular expression, it should be passed through preg_quote() to ensure that any characters with special meaning are escaped.

Using a preg_ function offers the deepest tooling such as case-insensitivity, multibyte parsing, and word boundaries ...if desirable.

Reversing the filtration with preg_grep() is simply done with a function flag. To reverse the filtration with non-regex functions, just invert the return value or the comparison on the return value (depending on which technique you use.

Codes (Demo)

function keepIfStartsWith_regex($haystack, $needle) {
    return preg_grep('/^' . preg_quote($needle, '/') . '/', $haystack);
}

function removeIfStartsWith_regex($haystack, $needle) {
    return preg_grep('/^' . preg_quote($needle, '/') . '/', $haystack, PREG_GREP_INVERT);
}

For case-sensitive matching the leading characters of a string in PHP8, use iterated calls of the concise and intuitive str_starts_with() function.

function keepIfStartsWith_PHP8($haystack, $needle) {
    return array_filter($haystack, fn($v) => str_starts_with($v, $needle));
}

function removeIfStartsWith_PHP8($haystack, $needle) {
    return array_filter($haystack, fn($v) => !str_starts_with($v, $needle));
}

For PHP versions under 8, you can make iterated calls of strpos() for case-sensitive or stripos() for case-insensitive matching. You must explicitly check if the return value is identical to 0 because performing a loose comparison (type-juggled comparison) will mistake 0 for false when no match is found.

function keepIfStartsWith_PHP7_4($haystack, $needle) {
    return array_filter($haystack, fn($v) => strpos($v, $needle) === 0);
}

function removeIfStartsWith_PHP7_4($haystack, $needle) {
    return array_filter($haystack, fn($v) => strpos($v, $needle) !== 0);
}

function keepIfStartsWith_sub7_4($haystack, $needle) {
    return array_filter($haystack, function($v) use($needle) { return strpos($v, $needle) === 0; });
}

function removeIfStartsWith_sub7_4($haystack, $needle) {
    return array_filter($haystack, function($v) use($needle) { return strpos($v, $needle) !== 0; });
}
0
ixany On

PHP 8 (2021):

I’m using str_starts_with for this purpose.

Performs a case-sensitive check indicating if haystack begins with needle.

→ Documentation

str_starts_with("car_porsche", "car_");
0
casraf On

I think you can use array_filter() for that purpose.

0
Pete B On

You can write a simple routine which gives you the option of dropping the prefix in your returned array:

function filter_by_key_prefix ( $arr, $prefix, $drop_prefix=false ) {
        $params = array();
        foreach( $arr as $k=>$v ) {
            if ( strpos( $k, $prefix ) === 0 ) {
                if ( $drop_prefix ) {
                    $k = substr( $k, strlen( $prefix ) );
                }
                $params[ $k ] = $v;
            }
        }
        return $params;
    }
0
InVeX On

Regexp takes much more time to process, it`s better to use strpos() in this case:

foreach($arr AS $key => $val)
if(strpos(" ".$val, "car_") == 1)     
    $cars[$key] = $val;

This also works with keys: