如何“合并”将某些数组元素放入同一数组的元素中?

发布于 2024-09-25 17:38:54 字数 1422 浏览 0 评论 0原文

$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]);
    }
}

有什么想法吗?

$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 is an array i have to edit, Bar the edits i need to do.

I have to create another element in Foo array containing the elements pointed in Bar, and delete the originals from Foo.

So, with the array, the final array should be:

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'
            )
        )
    )
)

I've build this recursive function, but works only for the first level of the array:

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]);
    }
}

Any ideas?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

少年亿悲伤 2024-10-02 17:38:54

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

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

意识到这一点,当你在 $bar 中看到键“0”时,很明显我们应该查看该值并将该 key=>value 对移动到$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 函数可以减少一些代码,但是你正在谈论从任意长度、任意深度和任意次数的数组中删除任意元素......

The biggest issue with your script at the moment is that you assume an element without a key is a stand-alone construct. The array $bar actually looks like this to PHP:

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

Realizing this, when you see the key '0' in $bar it's obvious we should look at the value and move that key=>value pair to $foo['merged'], but it becomes more complicated when you see '6'. It's even more complicated when you realize you can't just nest foreach() loops since there could be potentially infinite levels to this array.

The trick to dealing with an arbitrary number of levels in any abstract data type is a recursive function with a static counter (for keeping track of level). This way we can keep going deeper into $bar, but we back out to exactly where we left out when we're done. If we make the counter an arary we can keep track of how we got to where we are. This way we can find the element within $foo later.

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

This is kind of sloppy, but what you requested involved some pretty high-level constructs and some complicated logic. There may be a few PHP functions I haven't memorized that could shave down a little bit of the code, but you're talking about removing arbitrary elements from arrays of arbitrary length with arbitrary depths and arbitrary number of times...

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文