Функция рекурсивного поиска, которая сужает результаты на каждой итерации - PullRequest
0 голосов
/ 12 мая 2019

Я хочу написать функцию поиска, которая может рекурсивно искать в массиве и сужать результаты на каждой итерации.Идея состоит в том, что он находит первый набор результатов, затем продолжает этот результат и ищет его снова, чтобы найти следующий набор результатов.Критерии поиска представлены в виде массива с иглами.У меня уже есть основная функция, но результаты не такие, как ожидалось.

Я написал рекурсивную функцию, которая работает.Однако итерации не дают мне мой окончательный результат.

$array = array(
    0 => array('id' => 1, 'currency' => 'EUR', 'name' => 'NL', 'country_code' => 31), 
    1 => array('id' => 2, 'currency' => 'EUR', 'name' => 'DE', 'country_code' => 49),
    2 => array('id' => 3, 'currency' => 'EUR', 'name' => 'FR', 'country_code' => 33),
    3 => array('id' => 4, 'currency' => 'EUR', 'name' => 'BE', 'country_code' => 32),
    4 => array('id' => 5, 'currency' => 'USD', 'name' => 'US', 'country_code' => 1),
    5 => array('id' => 6, 'currency' => 'Rand', 'name' => 'SAF', 'country_code' => 27),
    6 => array('id' => 7, 'currency' => 'Rubbles', 'name' => 'RUS', 'country_code' => 7),
    7 => array('id' => 8, 'currency' => 'EUR', 'name' => 'IT', 'country_code' => 39),
    8 => array('id' => 9, 'currency' => 'Pound', 'name' => 'GB', 'country_code' => 44),
); //list of countries which needs to searched

$query = array('currency' => 'EUR', 'id' => 8, 'country_code' => 49); //search needles

function _searchData(array $array, array $query, $counter=0) 
{
  $result = array();
  $matches_found = array();

  if($array){
     $i = $counter; //set counter, start with 0
     $keys = array_keys($query); //get query keys
     $vals = array_values($query); //get query values
     $max = count($keys); //set max_count to limit iteration

     foreach($array as $arrkey => $arrval){
       if(isset($arrval[$keys[$i]]) && $arrval[$keys[$i]] == $vals[$i] && $i < $max){ 
         $matches_found = $this->_searchData($arrval, $query, $i++); //return result, increment counter
         if($matches_found){    
           $arrval = $matches_found; //overwrite result array           
          }
       $result[] = $arrval;  
     }
   }
  return $result;
}
Expected result = 
**it should fail on the 3rd iteration because "country_code" does not match 
on result id 8.  

Я думаю, что моя главная проблема со счетчиком, так как его нужно увеличить.В цикле foreach я не могу получить полный контроль.У меня есть попытки сохранить match_found и повторно использовать его вне цикла, но это тоже не работает.

Цель функции - сузить результат на каждой итерации, чтобы завершить финальный набор результатов какэто соответствует меньшему количеству пар ключ-значение.Ps, может быть, есть более простой способ поиска в массиве с большим набором игл, и я всегда открыт для других предложений, но моя главная цель - запустить эту рекурсивную функцию, так как для меня наиболее разумно добиться желаемогоРезультаты.Также с точки зрения гибкости, поскольку я могу иметь столько поисковых игл, сколько захочу.Я надеюсь, что кто-то может направить меня в правильном направлении.Заранее спасибо!

1 Ответ

2 голосов
/ 13 мая 2019

Я думаю, что вы можете сделать намного проще с учетом ваших требований, например ::

<?php

$in = [
    ['id' => 1, 'currency' => 'EUR',     'name' => 'NL'],
    ['id' => 2, 'currency' => 'EUR',     'name' => 'DE'],
    ['id' => 3, 'currency' => 'EUR',     'name' => 'FR'],
    ['id' => 4, 'currency' => 'EUR',     'name' => 'BE'],
    ['id' => 5, 'currency' => 'USD',     'name' => 'US'],
    ['id' => 6, 'currency' => 'Rand',    'name' => 'SAF'],
    ['id' => 7, 'currency' => 'Rubbles', 'name' => 'RUS'],
    ['id' => 8, 'currency' => 'EUR',     'name' => 'IT'],
    ['id' => 9, 'currency' => 'Pound',   'name' => 'GB'],
];

$query = ['currency' => 'EUR', 'id' => 8]; //search needles

// array_filter will use the given callback to check every entry
$out = array_filter($in, function(array $candidate) use ($query) {
    // iterate over query
    foreach ($query as $key => $predicate) {
        // if the key exists, but the value differs
        if (isset($candidate[$key]) && $candidate[$key] !== $predicate) {
            // it should not be included
            return false;
        }
    }

    // otherwise, include
    return true;
});

print_r($out);

демо: https://3v4l.org/aAZPP

ref: https://www.php.net/manual/function.array-filter.php

...