strpos() with multiple needles? strpos() with multiple needles? php php

strpos() with multiple needles?


Here's some sample code for my strategy:

function strpos_array($haystack, $needles, $offset=0) {    $matches = array();    //Avoid the obvious: when haystack or needles are empty, return no matches    if(empty($needles) || empty($haystack)) {        return $matches;    }    $haystack = (string)$haystack; //Pre-cast non-string haystacks    $haylen = strlen($haystack);    //Allow negative (from end of haystack) offsets    if($offset < 0) {        $offset += $heylen;    }    //Use strpos if there is no array or only one needle    if(!is_array($needles)) {        $needles = array($needles);    }    $needles = array_unique($needles); //Not necessary if you are sure all needles are unique    //Precalculate needle lengths to save time    foreach($needles as &$origNeedle) {        $origNeedle = array((string)$origNeedle, strlen($origNeedle));    }    //Find matches    for(; $offset < $haylen; $offset++) {        foreach($needles as $needle) {            list($needle, $length) = $needle;            if($needle == substr($haystack, $offset, $length)) {                $matches[] = $offset;                break;            }        }    }    return($matches);}

I've implemented a simple brute force method above that will work with any combination of needles and haystacks (not just words). For possibly faster algorithms check out:


Other Solution

function strpos_array($haystack, $needles, $theOffset=0) {    $matches = array();    if(empty($haystack) || empty($needles)) {        return $matches;    }    $haylen = strlen($haystack);    if($theOffset < 0) {  // Support negative offsets        $theOffest += $haylen;    }    foreach($needles as $needle) {        $needlelen = strlen($needle);        $offset = $theOffset;        while(($match = strpos($haystack, $needle, $offset)) !== false) {            $matches[] = $match;            $offset = $match + $needlelen;            if($offset >= $haylen) {                break;            }        }    }    return $matches;}


I know this doesn't answer the OP's question but wanted to comment since this page is at the top of Google for strpos with multiple needles. Here's a simple solution to do so (again, this isn't specific to the OP's question - sorry):

    $img_formats = array('.jpg','.png');    $missing = array();    foreach ( $img_formats as $format )        if ( stripos($post['timer_background_image'], $format) === false ) $missing[] = $format;    if (count($missing) == 2)        return array("save_data"=>$post,"error"=>array("message"=>"The background image must be in a .jpg or .png format.","field"=>"timer_background_image"));

If 2 items are added to the $missing array that means that the input doesn't satisfy any of the image formats in the $img_formats array. At that point you know that you can return an error, etc. This could easily be turned into a little function:

    function m_stripos( $haystack = null, $needles = array() ){        //return early if missing arguments         if ( !$needles || !$haystack ) return false;         // create an array to evaluate at the end        $missing = array();         //Loop through needles array, and add to $missing array if not satisfied        foreach ( $needles as $needle )            if ( stripos($haystack, $needle) === false ) $missing[] = $needle;        //If the count of $missing and $needles is equal, we know there were no matches, return false..        if (count($missing) == count($needles)) return false;         //If we're here, be happy, return true...        return true;    }

Back to our first example using then the function instead:

    $needles = array('.jpg','.png');    if ( !m_strpos( $post['timer_background_image'], $needles ) )        return array("save_data"=>$post,"error"=>array("message"=>"The background image must be in a .jpg or .png format.","field"=>"timer_background_image"));

Of course, what you do after the function returns true or false is up to you.