【问题标题】:Group and sum data in fourth level of multidimensional array对多维数组第四级中的数据进行分组和求和
【发布时间】:2021-03-29 08:14:34
【问题描述】:

我有这个多维数组,我需要找出任何 SKU 的销售量。

我该怎么办?

    [Orders] => Array(
        [0] => Array(
            [transaction_id] => xxxx
            [date] => 1616277653
            [currency] => EUR
            [items] => Array(
                    [0] => Array(
                            [title] => Title
                            [quantity] => 200
                            [price] => 2.1
                            [sku] => 1T.810BK
                        )
                    [1] => Array(
                            [title] => Title
                            [quantity] => 250
                            [price] => 1.78
                            [sku] => 1090.005BK
                        )
              )
        )
        [1] => Array(
                [transaction_id] => 78079
                [date] => 1616597838
                [currency] => EUR
                [items] => Array(
                        [0] => Array
                            (
                                [title] => title
                                [quantity] => 3
                                [price] => 118.3
                                [sku] => 1.DIYBOX.ULT.638RE
                            )
                )
        )
)

目前我正在使用一个内部带有array_walk_recursive 的函数来提取关键 SKU 的所有值。 但是这样我就不能把它和数量的价值联系起来了。

所以这不可能是解决方案,除非我不能在函数内部传递 2 个 Key 变量。可以吗?

这是我此刻使用的功能:

        function array_value_recursive($key, array $arr){
                $val = array();
                array_walk_recursive($arr, function($v, $k) use($key, &$val){
                    if($k == $key) array_push($val, $v);
                });
                return count($val) > 1 ? $val : array_pop($val);
        }

        array_value_recursive('sku', $GetPendingOrders_obj);

我不确定传递两个键是否是理想的解决方案。 您认为我可以如何解决查找已售 SKU 数量的问题?

【问题讨论】:

  • 请在您的问题中准确表达您想要的输出。请始终将您的样本数组数据呈现为var_export() 的输出。您的样本数据可能应至少包含一个重复的 SKU,以便立即识别错误的答案。
  • 您的标题没有很好的可搜索性。可能类似于“在多维数组的第四级中对数据进行分组和求和”。
  • 嗨@mickmackusa,我不确定哪种方法是导出数据以查找已售 SKU 数量的最佳方法。可能是另一个多维数组,但不确定。你有什么想法吗?
  • 谢谢@mickmackusa 我将更改磁贴,并且我将使用此关键字进行谷歌搜索
  • 你的样本数组似乎有一个固定的结构,所以提取你想要的值应该没有问题。您不需要递归和动态访问。两个嵌套循环(一个在订单上,一个在订单项上)应该可以解决问题。

标签: php arrays multidimensional-array


【解决方案1】:

array_walk_recursive 确实是要走的路,但是,PHP 关联数组有点棘手,因为它们是字典并按顺序维护键,这意味着键的顺序与它们插入的方式相同第一名。要使其不受quantitysku 键的顺序的影响,请维护全局变量$sku$qt,并在找到它们对时切换到默认值。

片段:

<?php

$sku = '';
$qt = -1;
$result = [];
    
array_walk_recursive($arr, function($v, $k) use(&$sku,&$qt,&$result) {
    if($k === 'quantity'){
        if($sku !== ''){
            $result[ $sku ] = $result[ $sku ] ?? 0;
            $result[ $sku ] += $v;
            $sku = '';
        }else {
            $qt = $v;
        }
    }elseif($k === 'sku'){
        if($qt !== -1){
            $result[ $v ] = $result[ $v ] ?? 0;
            $result[ $v ] += $qt;
            $qt = -1;
        }else{
            $sku = $v;
        }
    }
});
 
 
print_r($result);

【讨论】:

  • 非常感谢,它运行良好。这对我的 PHP 知识来说太复杂了。我理解你向我解释的理论,现在我想研究你所做的,因为我想学习。再次感谢!
  • elseif 是 php 中符合 PSR-12 准则的一个词。
  • 我只做一点改动:$result[ $v ] += $qt; 使用+= 操作,如果有多个相同sku 的订单数量会更新。
  • @mickmackusa 感谢您告诉我。已更新。
  • @mickmackusa 你在猜测。 Orders 在数组的第一级有什么保证?您的解决方案假设如此,但我的解决方案无论如何都有效。
【解决方案2】:

另一种选择是使用array_column 的组合首先获取所有项目。然后使用带有 splat 的array_merge_recursive 将所有子项合并到一个多维中。最后,再次array_column 得到skuquantity

$items = array_column(array_merge_recursive(... array_column($data['Orders'], 'items')), 'quantity', 'sku');

最后,您将值与 sku 和数量进行密钥对。

【讨论】:

  • 这里有一个小提琴可以看到sample output
  • 谢谢@Kevin,这是另一种效果很好的简单方法。他没想到array_merge_recursive
  • 此解决方案不能用于对给定 sku 出现多次的数量“求和”。出于这个原因,这个答案不适合这个需要求和的问题。此外,array_merge_recursive() 的使用是不必要的开销——要从不同顺序展平子数组,您只需要 array_merge()splat。证明递归是不必要的:3v4l.org/N5Z7g 所以基本上,我是说这个答案是在用花哨的函数式编程欺骗研究人员。我想,这不完全是凯文的错,因为 OP 没有提供更好的minimal reproducible example
  • @mickmackusa 是的。不用担心,是的,当我提交此答案时,我已经知道如果它们位于 items 索引内的同一嵌套中,则此单行将不会合并数量,因此仅假设项目上的数量已经合并当它们在 OP 提供的数组中时。
【解决方案3】:

递归技术对于这项任务来说是不必要的开销。您无需访问每个叶节点即可生成所需的输出。

其他答案也不必费心对多次遇到的 skus 求和(以不同的顺序)。这是证据:https://3v4l.org/ZCRTu

我已经扩展了您的示例数据以包含一个多次出现的 sku。这样您就可以看到数量实际上是在必要时相加的。

代码:(Demo)

$result = [];
foreach ($data['Orders'] as $order) {
    foreach ($order['items'] as $item) {
        $result[$item['sku']] = ($result[$item['sku']] ?? 0) + $item['quantity'];
    }
}
var_export($result);

如果您更喜欢函数式编程,则需要先减少层数(换句话说,使用经典的扁平化技术——我更喜欢merge&spread),然后才能使用group&sum

代码:(Demo)

var_export(
    array_reduce(
        array_merge(
            ...array_column($data['Orders'], 'items')
        ),
        function($carry, $item) {
            $carry[$item['sku']] = ($carry[$item['sku']] ?? 0) + $item['quantity'];
            return $carry;
        }
    )
);

来自任一 sn-p 的输出:

array (
  '1T.810BK' => 200,
  '1090.005BK' => 550,
  '1.DIYBOX.ULT.638RE' => 3,
)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2018-09-01
    • 1970-01-01
    • 1970-01-01
    • 2014-10-20
    • 1970-01-01
    • 2012-10-19
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多