Pragmatism in the real world

substr_in_array

No matter what I want to do with an array, PHP usually has a first class method that does it. I was therefore surprised that in_array() didn’t handle substring matches. (I was sure there was a flag, but apparently not!)

No doubt everyone has their own version of this, but here’s mine so that I don’t have to recreate it next time:

/**
 * A version of in_array() that does a sub string match on $needle
 *
 * @param  mixed   $needle    The searched value
 * @param  array   $haystack  The array to search in
 * @return boolean
 */
function substr_in_array($needle, array $haystack)
{
    $filtered = array_filter($haystack, function ($item) use ($needle) {
        return false !== strpos($item, $needle);
    });

    return !empty($filtered);
}

Is there a better way of doing this?

6 thoughts on “substr_in_array

  1. I would actually prefer a foreach based implementation because it can return as soon as an match is found.

    That may count as micro-optimisation in most cases but the readability is not really hindered .

    function substr_in_array($needle, array $haystack)
    {
        foreach ($haystack as $item) {
            if (false !== strpos($item, $needle)) {
                return true;
            }
        }
    
        return false;
    }
    
  2. I might be tempted to use array_reduce instead of array_filter. Since the question is Does this substring exist in this array? and not How many times does this substring exist in this array? you can abuse PHP's short-circuit evaluation to avoid calling strpos for every element. This may show useful gains when $haystack is stupid big.

    /**
     * A version of in_array() that does a sub string match on $needle
     *
     * @param  mixed   $needle    The searched value
     * @param  array   $haystack  The array to search in
     * @return boolean
     */
    function substr_in_array($needle, array $haystack)
    {
        return array_reduce($haystack, function ($inArray, $item) use ($needle) {
            return $inArray || false !== strpos($item, $needle);
        }, false);
    }
    
  3. Using fnmatch() rather than strpos() allows you to do wildcarding and other clever filtering in your search

  4. I think your use of filter is clever, but I don't agree with the function name. substr() uses start/leght which is in array terms array_slice(), so it sounds weird and misleading. Why not find_in_array? Then you can return the filtered array as the name also don't make any allusion the bool type.

Comments are closed.