【问题标题】:How to sum multi-dimensional arrays based on some conditions?如何根据某些条件对多维数组求和?
【发布时间】:2019-10-18 11:12:21
【问题描述】:
 $arr = [ [
        '5'=>[
            'BG' => 50,
            'CH' => 60,
            'LG' => 50,
            'MT' => 40,
            'MO' => 80,
            'PH' => 60,
            'GE' =>null
        ]
    ], [
        '6'=>[
            'BG' => 90,
            'CH' => 60,
            'LG' => 60,
            'MT' => 50,
            'MO' =>null,
            'PH' => 50,
            'GE' =>null
        ]
    ],[
        '7'=>[
            'BG' => 80,
            'CH' => 55,
            'LG' => 65,
            'MT' => 50,
            'MO' =>null,
            'PH' => 50,
            'GE' => 55
        ]
    ]
  ];

对于每个 id 5、6 和 7,我想总结分数。 CH, PH, MO 和 LG 总是必须总结的。但是在总结了必修项目之后,我想根据以下条件总结其他项目。 如果 MO 为空,则取 BG、MT 和 GE 中最好的两个。如果MO不为null或大于等于0,我想从BG、MT或GE中取最好的一个。

所以总结结果如下:

Array
(
  [5] => Array
    (
        [score] => 300
    )
[6] => Array
    (
        [score] => 310
    )
[7] => Array
    (
        [score] => 305
    )
)

我试过foreach,但我无法解决问题。我该如何解决这个问题?

【问题讨论】:

  • 到目前为止你有什么尝试?
  • 我尝试了 foreach 循环。但不知道如何绕过这种情况。

标签: php arrays sorting multidimensional-array associative-array


【解决方案1】:

这里有更核心的方法来实现这一点,请查找 inline doc 进行解释,

$keys  = array_flip(['BG', 'MT', 'GE']); // best of how many keys
$Ckeys = array_flip(['CH', 'PH', 'MO', 'LG']); // compulsory keys
foreach ($arr as $key => $value) {
    // use to pass parameters to reduce function during call
    $temp[key($value)] = array_reduce($value, function (&$result, $a) use ($keys, $Ckeys) {
        // if mo empty then best of two else best of one
        $bestHowMany = (!empty($a['MO']) ? 1 : 2);
        // fetching best of keys from $keys
        $t           = array_intersect_key($a, $keys);
        // reverse sort and maintains keys
        arsort($t);
        // fetch top $bestHowMany Values
        $largest2 = array_slice($t, 0, $bestHowMany);
        // fetch compulsory values from CKeys
        $t1       = array_intersect_key($a, $Ckeys);
        // sum by merging compulsory and best of $bestHowMany values
        return array_sum(array_merge($t1, $largest2));
    });
}

工作demo

输出

Array
(
    [5] => 300
    [6] => 310
    [7] => 305
)

【讨论】:

  • 这给了我正确的解决方案。但是,在我的数组中,我需要通过子字符串检查 $keys。例如,要检查 MO,我需要使用 strpos(strtolower($keys),'O')!==false 而不是完整的字符串 MO。因为有时 MO 可能是 MOab..MOm 等。其他键也是如此。如果您可以帮助修改您对我的要求的回答,我将不胜感激。谢谢。
  • 您应该将您的问题更新为精确。我还不清楚“其他键也一样”这句话。这是什么意思,你能解释一下吗?
【解决方案2】:

在这里,我们可以先将三个数组全部相加,然后根据条件相减,我们的代码如下所示,

$arr = [[
    '5' => [
        'BG' => 50,
        'CH' => 60,
        'LG' => 50,
        'MT' => 40,
        'MO' => 80,
        'PH' => 60,
        'GE' => null,
    ],
], [
    '6' => [
        'BG' => 90,
        'CH' => 60,
        'LG' => 60,
        'MT' => 50,
        'MO' => null,
        'PH' => 50,
        'GE' => null,
    ],
], [
    '7' => [
        'BG' => 80,
        'CH' => 55,
        'LG' => 65,
        'MT' => 50,
        'MO' => null,
        'PH' => 50,
        'GE' => 55,
    ],
],
];

$sum_arr = array();
foreach ($arr as $key => $arr2) {
    foreach ($arr2 as $key2 => $value) {
        $sum_arr[$key2]["score"] = array_sum(array_values($value));
        $temp = [$value["BG"], $value["MT"], $value["GE"]];
        arsort($temp);
        if ($value["MO"] === null) {
            $sum_arr[$key2]["score"] -= $temp[2];
        } elseif ($value["MO"] != null && $value["MO"] >= 0) {
            $sum_arr[$key2]["score"] -= $temp[2] + $temp[1];
        } else {
            continue;
        }

    }

}

var_dump($sum_arr);

我的代码中很可能存在错误,或者我没有正确理解 if 条件,或者所需的输出不太可能不正确。不过调试起来应该不难。

输出

array(3) {
  [5]=>
  array(1) {
    ["score"]=>
    int(300)
  }
  [6]=>
  array(1) {
    ["score"]=>
    int(310)
  }
  [7]=>
  array(1) {
    ["score"]=>
    int(300)
  }
}

【讨论】:

    猜你喜欢
    • 2021-12-28
    • 2021-03-27
    • 2021-05-05
    • 2022-01-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-11-28
    相关资源
    最近更新 更多