2013-06-20 178 views
0

我需要查看Array1,从Array2中查找任何匹配序列,并更新Array1中相应的子数组。PHP - 在嵌套数组2中查找嵌套数组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) 
) 

因此我应该找到在草堆 “AA BB CCCC”(针[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] =>) 
) 

我有两个版本的代码是;

代码版本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针n的多个匹配 - 它只发现一个)第一个或b)最后一个)3)它匹配无论顺序/序列(我认为我以某种方式破坏了代码,并且它会匹配“cccc bb aa”,当Needles中的该顺序不存在时(它代之以“aa bb cccc”)。

我已经花了2天的时间,我做错了。

我已经尝试使用这两种解决方案(在foreach和对于方法)...但我不能让任何一方的工作。

+1

这对我来说不是很清楚你想要达到什么目的。你会使用所有的“针”还是只使用一个特定的针(例如,g为什么你不在上面的例子中将“aa”设置为“ddd”和“bb”设置为“dd”)? – gkalpak

+0

@ExpertSystem - 对不起,如果不是很清楚。基本上,有一个大的嵌套数组(干草堆),充满了子数组。我需要从一组较小的数组中找到匹配项,并使用较小的子数组(针)来更新Haystack。 ::如果有帮助,可以考虑通过查看订单和更新客户地址等方案 - 我浏览客户数据(干草堆),并更新邮编(针)的匹配。希望更清楚。 – theclueless1

回答

1

如果我明白你是什么正确试图实现,你coul ð像这样做(见代码中的注释):

/* 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个嵌套数组卡住了 - 唯一的办法就是在一堆嵌套的foreach中使用这个代码......是吗? – theclueless1

+0

好吧 - 由于环境而稍微改编(在一个类中,必须添加一个foreach循环才能从对象中获取针)......但它的工作原理!非常感谢@ExperSystem。 – theclueless1

+0

快速跟进...我已经调整它包含在现有的类中。当我经过大型干草堆(1K物品)和很多针(5K)时,它需要约5秒...是预期的吗?有没有什么明显的方法来加速它,或者它是否与这种迭代(由于嵌套等)有关? ::再次,谢谢@ExpertSystem - 太棒了! – theclueless1