如何将一些数组元素“合并”到同一个数组的元素中?

时间:2010-09-30 15:39:42

标签: php arrays recursion multidimensional-array

$foo = array(
    '1' => '2',
    '3' => array(
        '4' => '5'
    ),
    '6' => array(
        '7' => '8',
        '9' => '10',
        '11' => array(
            '12' => '13',
            '14' => '15'
        )
    )
);

$bar = array(
    '1',
    '6' => array(
        '7',
        '11' => array(
            '12'
        )
    )
);

Foo是我必须编辑的数组,Bar我需要做的编辑。

我必须在Foo数组中创建另一个元素,其中包含Bar中指向的元素,并从Foo中删除原始文件。

因此,对于数组,最终数组应为:

Array(
    '3' => array(
        '4' => '5'
    ),
    '6' => array(
        '9' => '10',
        '11' => array(
            '14' => '15'
        )
    ),
    'merged' => array(
        '1' => '2',
        '6' => array(
            '7' => '8',
            '11' => array(
                '12' => '13'
            )
        )
    )
)

我已经构建了这个递归函数,但只适用于数组的第一级:

foreach($bar AS $key => $value){
    if(is_array($value)){
        s($foo, $key, $value);
    }else{
        $foo['merged'][$value] = $foo[$value];
        unset($foo[$value]);
    }
}


function s(&$form, $key, $value){
    if(is_array($value)){
        foreach($value AS $k => $v){
            s($form, $k, $v);
        }
    }else{
        $form['merged'][$value] = $form[$value];
        unset($foo[$value]);
    }
}

有什么想法吗?

1 个答案:

答案 0 :(得分:1)

目前你的脚本最大的问题是你假设一个没有键的元素是一个独立的构造。数组$ bar 实际对PHP来说是这样的:

$bar = array(
    '0' => '1',
    '6' => array(
        '0' => '7',
        '11' => array(
            '0' => '12'
        )
    )
)

意识到这一点,当你在$ bar中看到键'0'时,显然我们应该查看该值并将该key =>值对移动到$ foo ['merged'],但是当你变得更加复杂时看'6'。当你意识到你不能只嵌套foreach()循环时会更复杂,因为这个数组可能存在无限级别。

在任何抽象数据类型中处理任意数量级别的技巧是具有静态计数器的递归函数(用于跟踪级别)。通过这种方式,我们可以继续深入$ bar,但我们会在完成后退回到我们遗漏的位置。如果我们让柜台成为一个图书馆,我们可以跟踪我们如何到达我们所处的位置。这样我们可以在$ foo中找到元素。

/* recursive_foobar is the only function you call */

function recursive_foobar(&$foo, $bar, &$merged){
    static $counter;
    if(is_empty($counter)){ // initialize counter the first time
        $counter = array();
    }
    foreach($bar as $key => $element){
        if(is_array($element)){
            $counter[] = $key;
            recursive_foobar($foo, $element, $merged[$key]);
        } else {
            $old_value = recursive_get($foo, array_push($counter, $element));
            recursive_remove($foo, array_push($counter, $element));
            array_merge($merged, $old_value);
        }
    }
    return $merged;
}

/* recursive_get returns a multi-level array containing the requested element at the lowest level */

function recursive_get($haystack, $key){
    static $return;
    if(count($key) > 1){
        $return[] = array(recursive_get($haystack[$key[0]], array_shift($key)));
    } else {
        $return[] = $haystack[$key[0]];
    }
    return $return;
}

/* recursive_remove will remove the requested element, leaving all containers untouched */

function recursive_remove(&$array, $key){
    if(count($key) > 1){
        recursive_remove($array[$key[0]], array_shift($key));
    } else {
        remove($array[$key[0]]) ???
    }
}

$foo['merged'] = array();
recursive_foobar($foo, $bar, $foo['merged']);

这有点草率,但你要求的是一些非常高级的结构和一些复杂的逻辑。可能有一些我没有记住的PHP函数可以削减一些代码,但是你正在讨论从任意长度和任意次数的任意长度的数组中删除任意元素......