合并多个平面关联数组并对共享键的值求和

发布于 2024-11-09 03:06:20 字数 883 浏览 2 评论 0原文

我正在寻找一个 array_merge() 函数,它不会替换值,而是添加它们。

例如,这是我正在尝试的代码:

echo "<pre>"; 

$a1 = array(
     "a" => 2
    ,"b" => 0
    ,"c" => 5
);

$a2 = array(
     "a" => 3
    ,"b" => 9
    ,"c" => 7
    ,"d" => 10
);

$a3 = array_merge($a1, $a2);
print_r($a3); 

可悲的是,这输出了:

Array
(
    [a] => 3
    [b] => 9
    [c] => 7
    [d] => 10
)

然后我尝试了,而不是 array_merge,只是简单地添加两个数组

$a3 = $a1 + $a2;

但这输出

Array
(
    [a] => 2
    [b] => 0
    [c] => 5
    [d] => 10
)

我真正想要的是能够通过根据需要创建尽可能多的数组,然后得到它们的总和。因此,在我的示例中,我希望输出为:

Array
(
    [a] => 5
    [b] => 9
    [c] => 12
    [d] => 10
)

当然,我可以使用许多 foreach 等构建一些函数,但我正在寻找一个更智能、更干净的解决方案。

I am looking for an array_merge() function that does NOT replace values, but ADDS them.

Example, this is the code I am trying:

echo "<pre>"; 

$a1 = array(
     "a" => 2
    ,"b" => 0
    ,"c" => 5
);

$a2 = array(
     "a" => 3
    ,"b" => 9
    ,"c" => 7
    ,"d" => 10
);

$a3 = array_merge($a1, $a2);
print_r($a3); 

Sadly, this outputs this:

Array
(
    [a] => 3
    [b] => 9
    [c] => 7
    [d] => 10
)

I then tried, instead of array_merge, just simply adding the two arrays

$a3 = $a1 + $a2;

But this outputs

Array
(
    [a] => 2
    [b] => 0
    [c] => 5
    [d] => 10
)

What I truly want is to be able to pass as many arrays as needed, and then get their sum. So in my example, I want the output to be:

Array
(
    [a] => 5
    [b] => 9
    [c] => 12
    [d] => 10
)

Of course I can schlepp and build some function with many foreach etc, but am looking or a smarter, cleaner solution.

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

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

发布评论

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

评论(4

舂唻埖巳落 2024-11-16 03:06:20
$sums = array();
foreach (array_keys($a1 + $a2) as $key) {
    $sums[$key] = (isset($a1[$key]) ? $a1[$key] : 0) + (isset($a2[$key]) ? $a2[$key] : 0);
}

可以使用错误抑制运算符将其缩短为以下内容,但它应该被认为是丑陋的:

$sums = array();
foreach (array_keys($a1 + $a2) as $key) {
    $sums[$key] = @($a1[$key] + $a2[$key]);
}

或者,一些映射:

$keys = array_fill_keys(array_keys($a1 + $a2), 0);
$sums = array_map(function ($a1, $a2) { return $a1 + $a2; }, array_merge($keys, $a1), array_merge($keys, $a2));

或者两种解决方案的组合:

$sums = array_fill_keys(array_keys($a1 + $a2), 0);
array_walk($sums, function (&$value, $key, $arrs) { $value = @($arrs[0][$key] + $arrs[1][$key]); }, array($a1, $a2));

我认为这些足够简洁,可以适应一个需要时就可以在现场计算它们,但是用一个接受无限数量的数组并对它们求和的函数来表示:

function array_sum_identical_keys() {
    $arrays = func_get_args();
    $keys = array_keys(array_reduce($arrays, function ($keys, $arr) { return $keys + $arr; }, array()));
    $sums = array();

    foreach ($keys as $key) {
        $sums[$key] = array_reduce($arrays, function ($sum, $arr) use ($key) { return $sum + @$arr[$key]; });
    }
    return $sums;
}
$sums = array();
foreach (array_keys($a1 + $a2) as $key) {
    $sums[$key] = (isset($a1[$key]) ? $a1[$key] : 0) + (isset($a2[$key]) ? $a2[$key] : 0);
}

You could shorten this to the following using the error suppression operator, but it should be considered ugly:

$sums = array();
foreach (array_keys($a1 + $a2) as $key) {
    $sums[$key] = @($a1[$key] + $a2[$key]);
}

Alternatively, some mapping:

$keys = array_fill_keys(array_keys($a1 + $a2), 0);
$sums = array_map(function ($a1, $a2) { return $a1 + $a2; }, array_merge($keys, $a1), array_merge($keys, $a2));

Or sort of a combination of both solutions:

$sums = array_fill_keys(array_keys($a1 + $a2), 0);
array_walk($sums, function (&$value, $key, $arrs) { $value = @($arrs[0][$key] + $arrs[1][$key]); }, array($a1, $a2));

I think these are concise enough to adapt one of them on the spot whenever needed, but to put it in terms of a function that accepts an unlimited number of arrays and sums them:

function array_sum_identical_keys() {
    $arrays = func_get_args();
    $keys = array_keys(array_reduce($arrays, function ($keys, $arr) { return $keys + $arr; }, array()));
    $sums = array();

    foreach ($keys as $key) {
        $sums[$key] = array_reduce($arrays, function ($sum, $arr) use ($key) { return $sum + @$arr[$key]; });
    }
    return $sums;
}
涙—继续流 2024-11-16 03:06:20

我的贡献:

function array_merge_numeric_values()
{
    $arrays = func_get_args();
    $merged = array();
    foreach ($arrays as $array)
    {
        foreach ($array as $key => $value)
        {
            if ( ! is_numeric($value))
            {
                continue;
            }
            if ( ! isset($merged[$key]))
            {
                $merged[$key] = $value;
            }
            else
            {
                $merged[$key] += $value;
            }
        }
    }
    return $merged;
}

根据需要向其传递任意数量的数组。请随意添加更多防御、接受多维数组的能力或类型检查。

演示:http://codepad.org/JG6zwAap

My contribution:

function array_merge_numeric_values()
{
    $arrays = func_get_args();
    $merged = array();
    foreach ($arrays as $array)
    {
        foreach ($array as $key => $value)
        {
            if ( ! is_numeric($value))
            {
                continue;
            }
            if ( ! isset($merged[$key]))
            {
                $merged[$key] = $value;
            }
            else
            {
                $merged[$key] += $value;
            }
        }
    }
    return $merged;
}

Pass as many arrays to it as you want. Feel free to add some more defense, ability to accept multidimensional arrays, or type checking.

Demo: http://codepad.org/JG6zwAap

揪着可爱 2024-11-16 03:06:20

没那么复杂
做类似的事情:

$a3 = $a1;

foreach($a2 as $k => $v) {
    if(array_key_exists($k, $a3)) {
       $a3[$k] += $v;
    } else {
       $a3[$k] = $v; 
    }
}

its not so complicate
do something like:

$a3 = $a1;

foreach($a2 as $k => $v) {
    if(array_key_exists($k, $a3)) {
       $a3[$k] += $v;
    } else {
       $a3[$k] = $v; 
    }
}
空城旧梦 2024-11-16 03:06:20

如果您需要一个可以接收不确定数量的数组的脚本,那么 array_merge_recursive() 会很好地将它们挤压在一起。只要理解,如果一个键只出现一次,那么它的值将仍然是一个标量值——这意味着在调用 array_sum() 之前,所有值都应该显式转换为数组类型以避免损坏。由于 array_map() 只接收一个数组作为输入,因此它将保留关联键。

代码:(Demo)

var_export(
    array_map(
        fn($v) => array_sum((array) $v),
        array_merge_recursive($a1, $a2, $a3)
    )
);

要处理两个输入数组:

您可以使用 array_reduce() 如果您希望有一个返回新数组的函数迭代器,但它有点吵。 (演示) (箭头函数之前的演示

var_export(
    array_reduce(
        array_keys($a2),
        fn($result, $k) => array_merge($result, [$k => ($result[$k] ?? 0) + $a2[$k]]),
        $a1
    )
);

否则,我建议使用清晰而简洁的经典 foreach() 循环。 (演示

$result = $a1;
foreach ($a2 as $k => $v) {
    $result[$k] = ($result[$k] ?? 0) + $v;
}
var_export($result);

If you need a script which can receive an indeterminant number of arrays, then array_merge_recursive() will squeeze them together nicely. Just understand that if a key only occurs once, then its value will remain a scalar value -- this means that before calling array_sum() all values should be explicitly cast to array-type to avoid breakage. Because array_map() is only receiving one array as input, it will preserve the associative keys.

Code: (Demo)

var_export(
    array_map(
        fn($v) => array_sum((array) $v),
        array_merge_recursive($a1, $a2, $a3)
    )
);

To handle your two input arrays:

You could use array_reduce() if you wish for a functional iterator which returns the new array, but it's a little noisy. (Demo) (Demo before arrow functions)

var_export(
    array_reduce(
        array_keys($a2),
        fn($result, $k) => array_merge($result, [$k => ($result[$k] ?? 0) + $a2[$k]]),
        $a1
    )
);

Otherwise, I recommend the clarity and brevity of a classic foreach() loop. (Demo)

$result = $a1;
foreach ($a2 as $k => $v) {
    $result[$k] = ($result[$k] ?? 0) + $v;
}
var_export($result);
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文