Jessie Stalk
Jessie Stalk

Reputation: 991

Working with substr_count() and arrays in PHP

So what I need is to compare a string to an array (string as a haystack and array as a needle) and get the elements from the string that repeat within the array. For this purpose I've taken a sample function for using an array as a needle in the substr_count function.

$animals = array('cat','dog','bird');
$toString = implode(' ', $animals);
$data = array('a');

function substr_count_array($haystack, $needle){
     $initial = 0;
     foreach ($needle as $substring) {
          $initial += substr_count($haystack, $substring);
     }
     return $initial;
}

echo substr_count_array($toString, $data);

The problem is that if I search for a character such as 'a', it gets through the check and validates as a legit value because 'a' is contained within the first element. So the above outputs 1. I figured this was due to the foreach() but how do I bypass that? I want to search for a whole string match, not partial.

Upvotes: 3

Views: 1846

Answers (2)

Ja͢ck
Ja͢ck

Reputation: 173562

Just throwing my solution in the ring here; the basic idea, as outlined by scrowler as well, is to break up the search subject into separate words so that you can compare whole words.

function substr_count_array($haystack, $needle) 
{
    $substrings = explode(' ', $haystack);

    return array_reduce($substrings, function($total, $current) use ($needle) {
        return $total + count(array_keys($needle, $current, true));
    }, 0);
}

The array_reduce() step is basically this:

$total = 0;
foreach ($substrings as $substring) {
    $total = $total + count(array_keys($needle, $substring, true));
}
return $total;

The array_keys() expression returns the keys of $needle for which the value equals $substring. The size of that array is the number of occurrences.

Upvotes: 0

scrowler
scrowler

Reputation: 24406

You can break up the $haystack into individual words, then do an in_array() check over it to make sure the word exists in that array as a whole word before doing your substr_count():

$animals = array('cat','dog','bird', 'cat', 'dog', 'bird', 'bird', 'hello');
$toString = implode(' ', $animals);
$data = array('cat');

function substr_count_array($haystack, $needle){
    $initial = 0;
    $bits_of_haystack = explode(' ', $haystack);
    foreach ($needle as $substring) {
        if(!in_array($substring, $bits_of_haystack))
            continue; // skip this needle if it doesn't exist as a whole word

        $initial += substr_count($haystack, $substring);
    }
    return $initial;
}

echo substr_count_array($toString, $data);

Here, cat is 2, dog is 2, bird is 3, hello is 1 and lion is 0.


Edit: here's another alternative using array_keys() with the search parameter set to the $needle:

function substr_count_array($haystack, $needle){
    $bits_of_haystack = explode(' ', $haystack);
    return count(array_keys($bits_of_haystack, $needle[0]));
}

Of course, this approach requires a string as the needle. I'm not 100% sure why you need to use an array as the needle, but perhaps you could do a loop outside the function and call it for each needle if you need to - just another option anyway!

Upvotes: 2

Related Questions