2013-06-20 2 views
0

Мне нужно просмотреть Array1, найти любые соответствующие последовательности из Array2 и обновить соответствующие подмассивы в Array1.PHP - Найти вложенный массив1 в вложенном массиве

У меня ранее была помощь по аналогичному вопросу; Find array in array, in sequence

Предыдущие решения работали фантастически - но на этот раз я имею дело с более сложными данными, и мне нужно обновить массив Haystack (а не просто возвращать совпадения).

Массив 1: Стог

Array ( 
    [0] => Array ([v1] => aa [v2] =>) 
    [1] => Array ([v1] => bb [v2] =>) 
    [2] => Array ([v1] => cccc [v2] =>) 
    [3] => Array ([v1] => bb [v2] =>) 
    [4] => Array ([v1] => aa [v2] =>) 
    [5] => Array ([v1] => bb [v2] =>) 
    [6] => Array ([v1] => cccc [v2] =>) 
    [7] => Array ([v1] => bb [v2] =>) 
) 

Массив 2: Иглы

Array ( 
    [0] => Array ([aa] => nnnn [bb] => nnn [cccc] =>n) 
    [1] => Array ([aa] => ddd [bb] => dd) 
) 

Таким образом, я должен найти "аа бб КЦИК" (игла [0]) в стогу, и обновить массив стали;

Array ( 
    [0] => Array ([v1] => aa [v2] => nnnn) 
    [1] => Array ([v1] => bb [v2] => nnn) 
    [2] => Array ([v1] => cccc [v2] => n) 
    [3] => Array ([v1] => bb [v2] =>) 
    [4] => Array ([v1] => aa [v2] =>) 
    [5] => Array ([v1] => bb [v2] =>) 
    [6] => Array ([v1] => cccc [v2] =>) 
    [7] => Array ([v1] => bb [v2] =>) 
) 

2 варианта кода, который у меня есть;

Код версия 1:

// cache array sizes 
$haystack_len = count($haystack); 
$needle_len = count($needle); 

// shortlist the possible starting keys 
$possible_keys = array_keys($haystack, $needle[0], true); 

$results = array(); 

foreach ($possible_keys as $index) { 
    // start searching 
    $i = $index; $j = 0; 
    while ($i < $haystack_len && $j < $needle_len) { 
     if ($haystack[$i] !== $needle[$j]) { 
      continue 2; // no match 
     } 
     ++$i; ++$j; 
    } 
    // match 
    $results[] = range($index, $index + $needle_len - 1); 
} 

print_r($results); 

и код версии 2:

function find_array_in_array($needle, $haystack) { 
    $keys = array_keys($haystack, $needle[0]); 
    $out = array(); 
    foreach ($keys as $key) { 
     $add = true; 
     $result = array(); 
     foreach ($needle as $i => $value) { 
      if (!(isset($haystack[$key + $i]) && $haystack[$key + $i] == $value)) { 
       $add = false; 
       break; 
      } 
      $result[] = $key + $i; 
     } 
     if ($add == true) { 
      $out[] = $result; 
     } 
    } 
    return $out; 
} 

Но они предназначены для работы с плоскими массивами;

$haystack = array('a', 'b', 'a', 'b', 'c', 'c', 'a', 'b', 'd', 'c', 'a', 'b', 'a', 'b', 'c'); 
$needle = array('a', 'b', 'c'); 

Вместо этого, мне нужно, чтобы они работали с массивами, как в верхней части (вложен, и иглы в поисках совпадений с иглой [ключ] к стогу [массив] [v1]

Хотя я вертел и faffed с ранее кодой, я не могу победить его в правильную форму :( я продолжаю идти через Еогеасп петлю для доступа к вещам, и попытался с помощью для() и т.д.

foreach ($needlebox as $needles){ 
    foreach ($needles as $needlekey=>$needlevalue){ 
     foreach ($haystack as $haystackkey=>$haystackvalues){ 

      // insert above methods 

     } 
    } 
} 

но я нажмите следующие проблемы: 1) Array2 (иглы) огромные, с такими же иглами, появляющимися несколько раз? 2) Я получаю только одно совпадение (даже если Array 1 содержит несколько совпадений с Array 2 Needle-n - он только находит a) первый или b) последний) 3) Он соответствует независимо от порядка/последовательности (я думаю, Я как-то сломал код, и он будет соответствовать «cccc bb aa», когда этого порядка в Needles не существует (вместо этого «aa bb cccc»).

Я уже провел 2 дня с этим удивлением, что Я сделал неправильно.

Я пытался использовать оба решения (в Еогеасп и тому методов) ... но я не могу получить один из них работать.

+1

Мне не очень ясно, чего вы пытаетесь достичь. Будете ли вы использовать все «иглы» или только определенные (например,g почему вы не устанавливаете «aa» в «ddd» и «bb» на «dd» в вашем примере вверху)? – gkalpak

+0

@ExpertSystem - извините, если это было не так понятно. В принципе, есть большой вложенный массив (стог сена), полный субматриц. Мне нужно найти совпадения из коллекции меньших массивов и использовать значение меньших вспомогательных массивов (игл) для обновления Haystack. :: Если это помогает, подумайте о таком сценарии, как просмотр заказов и обновление адреса клиента - я просматриваю данные клиента (стог сена) и обновляю совпадения почтового индекса (иглы). Надеюсь, что это яснее. – theclueless1

ответ

1

Если я правильно понял, что вы пытаясь достичь, вы coul d сделать это так (см комментарии в коде):

/* Process one needle (look into haystack 
    and modify it accordingly) */ 
function processNeedle(&$haystack, $needle) { 
    $needleKeys = array_keys($needle); 
    $needleValues = array_values($needle); 
    $needleLen = count($needle); 
    $haystackLen = count($haystack); 

    /* Find indexes where a match begins */ 
    $matches = array(); 
    for ($i = 0; $i < ($haystackLen - $needleLen + 1); $i++) { 
     $match = true; 
     for ($j = 0; $j < $needleLen; $j++) { 
      if ($haystack[$i + $j]["v1"] != $needleKeys[$j]) { 
       $match = false; 
       break; 
      } 
     } 
     if ($match) { 
      $matches[] = $i; 
      $i += $needleLen - 1; 
     } 
    } 

    /* Do the actual replacement for all matches */ 
    forEach ($matches as $startIdx) { 
     for ($j = 0; $j < $needleLen; $j++) { 
      $haystack[$startIdx + $j]["v2"] = $needleValues[$j]; 
     } 
    } 
} 

См, также, это short demo.

+0

Это отлично выглядит (и привязанная к странице замечательная). Проблема в том, что у меня есть gfot, я застрял с двумя вложенными массивами - и единственный способ, который я вижу, - использовать этот код в связке вложенных foreachs ... это правильно? – theclueless1

+0

Хорошо - немного адаптировано из-за обстоятельств (в классе, пришлось добавить петлю foreach, чтобы получить иглы от объекта ...) ... но это работает !!! Большое спасибо @ExperSystem. – theclueless1

+0

Быстрый переход ... Я адаптировал его для включения в существующий класс. Когда я прохожу через большой сенокос (предметы 1K) и много игл (5K), он занимает около 5 секунд ... это ожидалось? Есть ли какой-либо очевидный способ ускорить его, или он соответствует курсу с такой итерацией (из-за гнездования и т. Д.)? :: И снова, спасибо @ExpertSystem - это фантастика! – theclueless1