duanji1924 2013-06-20 18:55
浏览 40
已采纳

PHP - 在嵌套的array2中查找嵌套的array1

I need to look through Array1, finding any matching sequences from Array2, and update corresponding sub-arrays in Array1.

I previously had help on a similar question; Find array in array, in sequence

The previous solutions worked fantastically - but this time I'm dealing with more complicated data, and I need to update the Haystack array (rather than simply return the matches).

Array 1 : Haystack

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] => ) 
) 

Array 2 : Needles

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

Thus I should find "aa bb cccc" (needle[0]) in the haystack, and update the array to become;

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] => ) 
) 

The 2 versions of code I have are;

Code version 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);

and Code version 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;
}

But these are designed to work with flat arrays;

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

Instead, I need them to work with the arrays as per the top (nested, and the needles are looking for matches to the needle[key] to the haystack[array][v1]

Though I've fiddled and faffed with the earlier code, I cannot beat it into the right shape :( I keep going through foreach loops to access things, and tried using for() etc.

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

            // insert above methods

        }
    }
}

but I hit the following issues; 1) Array2 (Needles) is huge, with the same needles appearing multiple times? 2) I only get a single match (even if Array 1 contains multiple matches to Array 2 Needle-n - it only finds a) the first or b) the last) 3) It matches regardless of order/sequence (I think I broke the code somehow, and it will match "cccc bb aa", when that order in Needles does not exist (it's instead "aa bb cccc").

I've now spent 2 days faffing with this wondering what I've done wrong.

I've attempted to use both solutions (the foreach and the for methods) ... but I cannot get either of them to work.

  • 写回答

1条回答 默认 最新

  • duanaixuan7385 2013-06-20 20:09
    关注

    If I understand correctly what you are trying to achieve, you could do it like this (see comments in code):

    /* 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];
            }
        }
    }
    

    See, also, this short demo.

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论

报告相同问题?

悬赏问题

  • ¥50 potsgresql15备份问题
  • ¥15 Mac系统vs code使用phpstudy如何配置debug来调试php
  • ¥15 目前主流的音乐软件,像网易云音乐,QQ音乐他们的前端和后台部分是用的什么技术实现的?求解!
  • ¥60 pb数据库修改与连接
  • ¥15 spss统计中二分类变量和有序变量的相关性分析可以用kendall相关分析吗?
  • ¥15 拟通过pc下指令到安卓系统,如果追求响应速度,尽可能无延迟,是不是用安卓模拟器会优于实体的安卓手机?如果是,可以快多少毫秒?
  • ¥20 神经网络Sequential name=sequential, built=False
  • ¥16 Qphython 用xlrd读取excel报错
  • ¥15 单片机学习顺序问题!!
  • ¥15 ikuai客户端多拨vpn,重启总是有个别重拨不上