Я нашел, что вы достаточно подробно описали проблему, чтобы я мог использовать подход TDD для ее решения. Итак, поскольку я очень стараюсь быть парнем TDD, я написал тесты и функцию, чтобы тесты прошли. Наименования могут быть не идеальными, но их легко изменить. Алгоритм функции также может быть не самым лучшим, но теперь, когда есть тесты, рефакторинг должен быть очень простым и безболезненным.
Вот тесты:
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);
}
}
А вот и функция:
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;
}
Проверка необходимости оператора break
Следующий тест показывает, когда необходимо break
. Запустите этот тест как с оператором break
, так и без него внутри функции match
.
/**
* This test demonstrates the purpose of the BREAK statement in the
* implementation function. Without it, the needle will be matched twice.
* "hot" will be matched for each "Hotel" word.
*/
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);
}