【问题标题】:How to compare and later merge two multidimensional arrays如何比较和稍后合并两个多维数组
【发布时间】:2018-02-25 13:37:48
【问题描述】:

我正在尝试通过以下方式合并两个多维数组(示例数组只是示例,真实数组很长并且有数千个项目):

$array_a:

[0] => Array
    (
        [date] => 2018-02-25 15:12
        [request] => 0
    )
[1] => Array
    (
        [date] => 2018-02-25 15:13
        [request] => 0
    )
[2] => Array
    (
        [date] => 2018-02-25 15:14
        [request] => 0
    )
[3] => Array
    (
        [date] => 2018-02-25 15:15
        [request] => 0
    )

$array_b:

[0] => Array
    (
        [date] => 2018-02-25 15:12
        [request] => 11
    )
[1] => Array
    (
        [date] => 2018-02-25 15:13
        [request] => 5
    )
[2] => Array
    (
        [date] => 2018-02-25 15:15
        [request] => 2
    )

需要的结果:

[0] => Array
    (
        [date] => 2018-02-25 15:12
        [request] => 11
    )
[1] => Array
    (
        [date] => 2018-02-25 15:13
        [request] => 5
    )
[2] => Array
    (
        [date] => 2018-02-25 15:14
        [request] => 0
    )
[3] => Array
    (
        [date] => 2018-02-25 15:15
        [request] => 2
    )

有吗?谢谢。

【问题讨论】:

    标签: php arrays multidimensional-array array-merge


    【解决方案1】:

    我可以给你结果,但是我不知道回调正文中的逻辑。

    $array_c = array_values(array_reduce(array_merge($a, $b), function($carry, $item) {
        $carry[$item['date']] = $item;
        return $carry;
    }, []));
    

    https://3v4l.org/fSVoj

    我正在做的是组合数组(它们都是子集,所以没有固有的冲突),然后我通过并“减少”到数组键 > 值配对,键是日期/时间,值是集合。这给出了将每个日期/时间合并到该数组中的相同键的效果。在这种情况下,回调只是“记住”遇到的最后一个日期/时间块,因此“不确定需要什么”问题。

    最后,我得到了一个用索引替换日期/时间的数组版本 (array_values())。这也很有趣,因为如果将 array_values() 调用移到以后,按日期排序会相当容易。

    这给出了:

    array(4) {
      [0]=>
      array(2) {
        ["date"]=>
        string(16) "2018-02-25 15:12"
        ["request"]=>
        int(11)
      }
      [1]=>
      array(2) {
        ["date"]=>
        string(16) "2018-02-25 15:13"
        ["request"]=>
        int(5)
      }
      [2]=>
      array(2) {
        ["date"]=>
        string(16) "2018-02-25 15:14"
        ["request"]=>
        int(0)
      }
      [3]=>
      array(2) {
        ["date"]=>
        string(16) "2018-02-25 15:15"
        ["request"]=>
        int(2)
      }
    }
    

    可以做不同的事情,比如只保留第一个,或者添加每个请求(它们在第一个数组中都为零)。不过机制应该是一样的。

    【讨论】:

    • 有趣的方法! +1 不使用 foreach 和很好的数组函数组合:)
    • 这个解决方案对我来说仍然很神秘,但它确实有效。即使新的 key->value 数据对添加到 arrayA 或 arrayB 也可以工作,所以这就是为什么我将这个答案标记为正确的。但是对于我写的有问题的场景,两个上层解决方案也有效。非常感谢大家。
    • @Sid 是的,其实就是pretty easy把它参数化成一个函数。
    【解决方案2】:

    一种方法:

    foreach($a as $v) {
            $res[$v['date']] = $v['request'];
    }
    
    foreach($b as $v) {
            if(isset($res[$v['date']])) {
                    if($v['request'] > $res[$v['date']])
                            $res[$v['date']] = $v['request'];
            } else {
                    $res[$v['date']] == $v['request'];
            }
    }
    
    foreach($res as $k=>$v)
            $out[] = array("date" => $k, "request" => $v);
    

    其中$a$b 是您的数组,$out 是最终结果。

    它是如何工作的:

    由于我们正在比较日期并且我们知道它们是唯一的,因此我们将它们放入一个临时数组(在我的情况下为 $res)作为元素的键(数组的键是唯一的)。对于每个元素的值,我们比较请求的值并存储较大的值。

    所以,第一个foreach 循环遍历第一个数组并将元素添加到$res,形式如下:

    $res['2018-02-25 15:12'] = 0;
    

    第二个foreach 循环遍历第二个数组的所有元素,但是,在这里我们还想确保我们对请求使用更大的值。

    因此,if 逻辑检查元素是否存在,如果存在 - 获取请求的较大值并将其存储到日期。如果不是 - 它完全按照它在第一个 foreach 循环中所做的事情(创建新元素)。

    最后,我们想将数组放在一起,使其看起来像这样,所以我们循环 $res 并重新创建数组,就像原来的两个样子一样。生成的 $out 包含您请求的内容。

    【讨论】:

    • 我正在写解释。
    【解决方案3】:

    如果你必须添加值,你可以使用这样的东西:

    $out = [];
    // create new array using date as key, "object" as value.
    foreach ($arr1 as $itm) {
        $out[$itm['date']] = $itm;
    }
    // foreach each element of the second array,
    foreach ($arr2 as $itm) {
        // if it doesn't exists in the out array, simply add it
        if (!isset($out[$itm['date']])) $out[$itm['date']] = $itm ;
        // otherwise, add request to the first
        else $out[$itm['date']]['request'] += $itm['request'];
    }
    ksort($out); // Sort by date (Optional)
    $out = array_values($out); // get values to remove dates from keys
    print_r($out);
    

    输出:

    Array
    (
        [0] => Array
            (
                [date] => 2018-02-25 15:12
                [request] => 11
            )
    
        [1] => Array
            (
                [date] => 2018-02-25 15:13
                [request] => 5
            )
    
        [2] => Array
            (
                [date] => 2018-02-25 15:14
                [request] => 0
            )
    
        [3] => Array
            (
                [date] => 2018-02-25 15:15
                [request] => 2
            )
    
    )
    

    【讨论】:

    • 这个解决方案也有效!伙计们,我不知道-如何获得像您这样的大脑,如何获得这样的阵列经验? :)) 非常感谢。很抱歉,无法将您的答案和@man0v 标记为答案。
    • @Sid 不客气 :) 也谢谢你。 @man0v 解决方案采用更大的request,我的添加它们。选择符合您需要的答案 :) 另外,我使用了两个 foreach。
    • @Sid 虽然您确实使用了 2 个 foreach,但您确实对数组进行了排序。另外,array_value 是否在内部循环也是有争议的。
    • @man0v array_values 可能会在内部循环(我目前正在 PHP 源代码中搜索),但 foreach 在每次迭代时都复制了一个对象。但是,除非您在数组中有十万个值,否则它不会产生如此大的影响:)
    • @man0v 仅供参考:来自 /php-7.2.2/ext/standard/array.c“仅返回输入数组中的值” ,在内存指针内部循环并返回引用。
    猜你喜欢
    • 2020-04-21
    • 1970-01-01
    • 2013-11-26
    • 2021-05-13
    • 2013-05-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多