I found that you are describing the problem in sufficient detail so that I can use TDD to solve it. Therefore, since I try so hard to be a TDD guy, I wrote tests and a function to pass the tests. Namings may not be perfect, but they change easily. The function algorithm may also not be the best, but now that there are tests, refactoring should be very simple and painless.
Here are the tests:
class MultiMatcherTest extends PHPUnit_Framework_TestCase { public function testTheComparisonIsCaseInsensitive() { $needles = array('hot'); $haystack = array('Southern Hotel'); $result = match($needles, $haystack); $this->assertEquals(array('Southern Hotel' => 1), $result); } public function testNeedleMatchesOnlyCharsAtBeginningOfWord() { $needles = array('resta'); $haystack = array('Errestas'); $result = match($needles, $haystack); $this->assertEquals(array('Errestas' => 0), $result); } public function testMatcherCountsNeedlesNotOccurences() { $needles = array('hot'); $haystack = array('Southern Hotel', 'Grange Restaurant & Hotel'); $expected = array('Southern Hotel' => 1, 'Grange Restaurant & Hotel' => 1); $result = match($needles, $haystack); $this->assertEquals($expected, $result); } public function testAcceptance() { $needles = array('ba','hot','resta'); $haystack = array( 'Southern Hotel', 'Grange Restaurant & Hotel', 'Austral Hotel', 'Barsmith Hotel', 'Errestas', ); $expected = array( 'Southern Hotel' => 1, 'Grange Restaurant & Hotel' => 2, 'Austral Hotel' => 1, 'Barsmith Hotel' => 2, 'Errestas' => 0, ); $result = match($needles, $haystack); $this->assertEquals($expected, $result); } }
And here is the function:
function match($needles, $haystack) { // The default result will containg 0 (zero) occurences for all $haystacks $result = array_combine($haystack, array_fill(0, count($haystack), 0)); foreach ($needles as $needle) { foreach ($haystack as $subject) { $words = str_word_count($subject, 1); // split into words foreach ($words as $word) { if (stripos($word, $needle) === 0) { $result[$subject]++; break; } } } } return $result; }
Verify that a break statement is required
The following test shows when break is required. Run this test with or without a break statement inside the match function.
public function testMatcherCountsNeedlesNotOccurences2() { $needles = array('hot'); $haystack = array('Southern Hotel Hotel'); $expected = array('Southern Hotel Hotel' => 1); $result = match($needles, $haystack); $this->assertEquals($expected, $result); }