2013-06-20 5 views
0

Array1을 살펴보고 Array2에서 일치하는 시퀀스를 찾고 Array1의 해당 하위 배열을 업데이트해야합니다.PHP - 중첩 된 array2에서 중첩 된 array1 찾기

나는 이전에 비슷한 질문을했습니다. 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 : 바늘 I는 덤에서 "단 비비 CCCC"을 (바늘 [0]) 찾은으로 어레이를 업데이트해야 따라서

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

지다;

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 문을 통해 계속 올바른 모양 :( 으로 이길 수없는 것들에 액세스 할 수 루프, 그리고() 등

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

      // insert above methods 

     } 
    } 
} 

하지만 난에 사용 시도 다음 문제를 해결하십시오 : 1) Array2 (Needles) is 거대한, 같은 바늘이 여러 번 나타납니다? 2) 배열 1에 배열 2 Needle-n과 일치하는 항목이 여러 개 있어도 하나의 일치 항목 만 가져옵니다 (첫 번째 또는 두 번째) 3) 순서/순서에 관계없이 일치합니다. 어떻게 든 코드가 깨졌고 바늘의 순서가 존재하지 않을 때 "cccc bb aa"와 일치합니다 (대신 "aa bb cccc"가됩니다).

이제이 질문에 2 일을 보냈습니다. 내가 잘못 했어.

나는 두 솔루션 (foreach 문 및 방법에 대한)를 사용하려고 시도했습니다 ...하지만 난 그들 중 하나가 동작하지 않습니다.

+1

달성하려는 목표가 분명하지 않습니다. 당신은 모든 "바늘"또는 단지 특정한 것 (예를 들어,g 왜 상단에있는 예에서 "aa"를 "ddd"로 설정하고 "bb"를 "dd"로 설정하지 않습니까? – gkalpak

+0

@ExpertSystem - 분명하지 않은 경우 미안합니다. 기본적으로 하위 배열로 가득 찬 큰 중첩 배열 (haystack)이 있습니다. 작은 배열 컬렉션에서 일치 항목을 찾고 작은 배열 (바늘)의 값을 사용하여 건초 더미를 업데이트해야합니다. :: 도움이된다면 주문을보고 고객 주소를 업데이트하는 것과 같은 시나리오를 생각해 봅니다 .- 클라이언트 데이터 (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했습니다 문제는 2 중첩 된 배열에 붙어 있어요 - 볼 수있는 유일한 방법은 중첩 된 foreachs이이 코드를 사용하는 것입니다 ... 맞습니까? – theclueless1

+0

좋아요 - 상황에 따라 약간 수정되었습니다 (클래스에서 바늘을 얻기 위해 foreach 루프를 추가해야했습니다 ...)하지만 작동합니다 !!! 대단히 감사합니다. @ExperSystem. – theclueless1

+0

빠른 속행 ... 나는 그것을 기존의 클래스에 포함시키기 위해 그것을 수정했다. 큰 건초 더미 (1K 품목)와 많은 바늘 (5K)을 통과 할 때 약 5 초가 걸립니다 ... 예상되는 것입니까? 속도를 높이기위한 분명한 방법이 있습니까? 아니면 중첩 등으로 인해 이러한 종류의 반복이있는 코스의 파입니까? :: 다시 한번 감사드립니다. @ExpertSystem - 환상적입니다! – theclueless1