简体   繁体   中英

search string with array of values with PHP

I am trying to search a list of files and only perform work on the files that have names that contain a few values in an array. I am hoping to not have to loop through the array each time I have a new filename.
ala-

$needle = array('blah', 'bleh');
foreach($file_list as $file)
{
    foreach($needle as $need)
       if(strstr($file, $need) !== false)
          {
             // do something...
          }
}

I just need to know if one of the strings in the array is in the filename, not the location of the string.

I would like to use something similar to strstr() but it does not allow an array to be used as the needle.

ie-

if(strstr($haystack, array('blah', 'bleh')))
{
   // do something...
}

I would prefer to stay away from regular expressions, it seems to be a sledge for a hammer's job. any ideas?

IMO it is fine to use regular expressions here:

$pattern  = '/' . implode('|', array_map('preg_quote', $needle)) . '/i';

foreach($file_list as $file) {
    if(preg_match($pattern, $file)) {
    // do something
    }
}

Reference: preg_quote


Here is a more "creative" way to do it (but it uses internal loops and is very likely slower, as you actually loop several times over the array):

function cstrstr($haystack, $needle) {
    return strstr($haystack, $needle) !== false;
}

foreach($file_list as $file) {
    if(array_sum(array_map('cstrstr', 
                       array_pad(array($file), count($needle), $file), 
                       $needle))) {
        // do something
    }
}

But the advantages with the regex should be obvious: You have to create the pattern only once whereas in the "funny" solution you always have to create an array of length count($needle) for every $file .

Patrick,

You can use in_array(). Example:

foreach($file_list as $file){

   if(in_array($file, $needle)){
     //--------------
     // Needle found
   }
}

You can find more examples here: http://php.net/manual/en/function.in-array.php

This will perform an action on all the files that contain all the needles inside their name

// Loop through files
foreach($files as $file){
    foreach($needles as $needle){
        // if filename does not contain this needle
        if(strpos($file, $needle) === false)
            continue 2; // skip to next file
    }
    // this file matches criteria. do smth on this file
}

Do not use preg_match() if you only want to check if one string is contained in another string. Use strpos() instead as it will be faster. http://php.net/manual/en/function.preg-match.php

$needle = array('blah', 'bleh');

foreach ($file_list as $file) {

    $result = $this->searchStrpos($file, $needle);

        if ($result !== false) {

            // do something...
        }
    }

/**
 * 
 * @param String $string String search
 * @param mixed $needle
 * @param Boolean $onlyFirst return true but 
 * @return Boolean Return boolean for search
 */
private function searchStrpos($string, $needle, $onlyFirst = true) {
    if (is_array($needle)) {
        foreach ($needle as $item) {
            $result = strpos($string, $item);
            if ($result !== false && $onlyFirst) {
                break;
            }
        }
    } else {
        $result = strpos($string, $needle);
    }

    return $result;
}

in_array may work just fine, however it would require exact matches in your needle array.

You could implode the array with some hash-string, and use the result with strstr or strposstr variant returns the first occurrence, pos only the position of the first occurrence— Make sure to have a very unique string, with both an uncommon prefix and suffix. This is rather a quick and dirty approach, but it may just work in your situation.

EDIT I was just thinking, why don't you want to use a loop? It'll be much faster than concatenating all elements from an array. Your question if there is a function to find partial matches using a reference array: it's not build-in, so you'd better use your own loop (or implement some function to do it, using a loop of course)

if( strstr( implode( " ", $array ), $search )  { //found   }

But a function with loop and return when found is faster and less memory consuming.

function searchArrayFast( $array, $search ) { foreach ( $array as $a ) { if( strstr( $a, $search)){ return true; } } return false; }

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