如何比较并稍后合并两个多维数组

时间:2020-12-28 12:07:08

I am trying to merge two multidimensional arrays in following way (example arrays are only examples, real ones are very long and have thousands of items):

我试图以下面的方式合并两个多维数组(示例数组只是示例,真实数组很长,有数千个项目):

$array_a:

$ 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:

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

Needed result:

需要的结果:

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

Any? Thanks.

任何?谢谢。

3 个解决方案

#1


3  

I can give you the result, however I don't know the logic that goes in the callback body.

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

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

https://3v4l.org/fSVoj

https://3v4l.org/fSVoj

What I'm doing is combining the arrays (they're all subset'd, so no inherent conflicts), then I go through and "reduce down" to an array key > value pairing, the key being the date/time, the value being the set. This gives the effect of coalescing each date/time to the same key in that array. The callback in this case simply "remembers" the last date/time block encountered, hence the "not sure what's needed" question.

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

Lastly, I get a version of the array with the date/times replaced with indexes (array_values()). This is also interesting, because sorting by date would be fairly easy if the array_values() call were moved to later.

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

This gives:

这给出了:

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

Different things can be done, like only keep the first, or add each request (they're all zero in the first array). The mechanism should be the same though.

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

#2


3  

One way to go:

一种方法:

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

where $a and $b are your arrays and $out is the final result.

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

How it works:

怎么运行的:

Since we are comparing the dates and we know they are unique, we put them into a temporary array(in my case $res) as keys of the elements(keys of arrays are unique). For values of each element we compare the values of requests and store the bigger one.

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

So, the first foreach loop loops over the first array and adds elemenets to $res in the form of:

因此,第一个foreach循环遍历第一个数组,并以以下形式将elemenets添加到$ res:

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

The second foreach loop loops over all elements of the second array, however, in here we also want to make sure we are using the bigger value for requests.

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

So this is, the if logic checks if the element exists, and if it does - gets the bigger value for requests and stores it to the date. If not - it does exactly what it did in the first foreach loop(creates new element).

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

Lastly, we want to put the array together to how it looked like, so we loop over $res and re-create the array as the original two looked like. The resulting $out holds what you requested.

最后,我们希望将数组放在一起,看看它是什么样的,所以我们循环遍历$ res并重新创建数组,就像原来的两个看起来一样。结果$ out保存您的请求。

#3


2  

If you have to add values, you could use something like this :

如果必须添加值,可以使用以下内容:

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

Outputs :

产出:

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
        )

)

#1


3  

I can give you the result, however I don't know the logic that goes in the callback body.

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

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

https://3v4l.org/fSVoj

https://3v4l.org/fSVoj

What I'm doing is combining the arrays (they're all subset'd, so no inherent conflicts), then I go through and "reduce down" to an array key > value pairing, the key being the date/time, the value being the set. This gives the effect of coalescing each date/time to the same key in that array. The callback in this case simply "remembers" the last date/time block encountered, hence the "not sure what's needed" question.

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

Lastly, I get a version of the array with the date/times replaced with indexes (array_values()). This is also interesting, because sorting by date would be fairly easy if the array_values() call were moved to later.

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

This gives:

这给出了:

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

Different things can be done, like only keep the first, or add each request (they're all zero in the first array). The mechanism should be the same though.

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

#2


3  

One way to go:

一种方法:

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

where $a and $b are your arrays and $out is the final result.

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

How it works:

怎么运行的:

Since we are comparing the dates and we know they are unique, we put them into a temporary array(in my case $res) as keys of the elements(keys of arrays are unique). For values of each element we compare the values of requests and store the bigger one.

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

So, the first foreach loop loops over the first array and adds elemenets to $res in the form of:

因此,第一个foreach循环遍历第一个数组,并以以下形式将elemenets添加到$ res:

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

The second foreach loop loops over all elements of the second array, however, in here we also want to make sure we are using the bigger value for requests.

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

So this is, the if logic checks if the element exists, and if it does - gets the bigger value for requests and stores it to the date. If not - it does exactly what it did in the first foreach loop(creates new element).

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

Lastly, we want to put the array together to how it looked like, so we loop over $res and re-create the array as the original two looked like. The resulting $out holds what you requested.

最后,我们希望将数组放在一起,看看它是什么样的,所以我们循环遍历$ res并重新创建数组,就像原来的两个看起来一样。结果$ out保存您的请求。

#3


2  

If you have to add values, you could use something like this :

如果必须添加值,可以使用以下内容:

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

Outputs :

产出:

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
        )

)