返回

二维数组透视与计数:PHP 实现状态转换与零值填充

php

透视与计数:转换二维数组并填充默认零值列

在处理数据时,我们经常需要对二维数组进行形式转换和聚合操作。本文将探讨一种常见情况:如何透视一个二维数组,并对分组值进行计数,最终生成一个带有默认零值列的新二维数组。

问题分析

给定的二维数组表示用户在不同步骤的状态。目标是将数据透视为以步骤为中心,并统计每个步骤中不同状态的数量,如“accepted”,“refused”和“waiting”。 如果某个步骤没有出现特定状态,则该状态的计数应为零。

解决方案

下面将介绍两种方法来解决这个问题:一种是使用循环迭代,另一种是利用函数式编程思想。

方案一:循环迭代

这种方法通过嵌套循环遍历原始数组,并累加每个状态的计数。

原理:

  1. 初始化一个空的目标数组,用于存储透视后的结果。
  2. 遍历原始数组中的每个用户及其步骤状态。
  3. 对于每个步骤,检查目标数组中是否已存在该步骤的记录。
    • 如果不存在,则创建一个新记录,并将所有状态的计数初始化为零。
    • 如果存在,则根据当前步骤的状态,增加相应状态计数器的值。

代码示例 (PHP):

<?php

$results = [
    "User_1" => [
        "Step_1" => "accepted",
        "Step_2" => "accepted",
        "Step_3" => "waiting",
        "Step_4" => "refused"
    ],
    "User_2" => [
        "Step_1" => "waiting",
        "Step_2" => "accepted",
        "Step_3" => "accepted",
        "Step_4" => "refused"
    ],
];

$steps = [];

foreach ($results as $user => $userSteps) {
    foreach ($userSteps as $step => $status) {
        if (!isset($steps[$step])) {
            $steps[$step] = [
                'acceptedSum' => 0,
                'refusedSum' => 0,
                'waitingSum' => 0,
            ];
        }
        switch ($status) {
            case 'accepted':
                $steps[$step]['acceptedSum']++;
                break;
            case 'refused':
                $steps[$step]['refusedSum']++;
                break;
            case 'waiting':
                $steps[$step]['waitingSum']++;
                break;
        }
    }
}

print_r($steps);
?>

操作步骤:

  1. 将代码保存为 .php 文件 (例如 pivot_count.php)。
  2. 通过命令行运行: php pivot_count.php

该代码会输出透视后的数组,其中包含每个步骤的“accepted”,“refused”和“waiting”状态计数。

安全建议:

  • 确保输入数据格式符合预期,避免出现类型错误。
  • 对状态值进行校验,防止出现未定义的状态导致程序逻辑错误。

方案二:函数式编程 (PHP)

这种方法利用 PHP 的数组函数,以更简洁的方式实现相同的逻辑。

原理:

  1. 使用 array_keysarray_unique 获取所有可能的状态。
  2. 初始化状态计数模板。
  3. 遍历原始数组,使用 array_reduce 累积每个步骤的状态计数。
  4. 循环遍历步骤,若某个状态没有出现则填补并设值为0。

代码示例 (PHP):

<?php
$results = [
    "User_1" => [
        "Step_1" => "accepted",
        "Step_2" => "accepted",
        "Step_3" => "waiting",
        "Step_4" => "refused"
    ],
    "User_2" => [
        "Step_1" => "waiting",
        "Step_2" => "accepted",
        "Step_3" => "accepted",
        "Step_4" => "refused"
    ],
];

$statuses = array_unique(array_reduce($results, function($carry, $item){
        return array_merge($carry,array_values($item));
    },[]));
$statusTemplate = array_reduce($statuses,function($carry,$item){
    $carry[$item.'Sum'] = 0;
    return $carry;
},[]);

$steps = [];
foreach($results as $userSteps){
    foreach($userSteps as $step => $status){
        if(!isset($steps[$step])){
            $steps[$step] = $statusTemplate;
        }
        $steps[$step][$status.'Sum']++;
    }
}

print_r($steps);
?>

操作步骤:

  1. 将代码保存为 .php 文件 (例如 pivot_count_functional.php)。
  2. 通过命令行运行: php pivot_count_functional.php

该代码会产生与方案一相同的输出结果。函数式编程方法通常更简洁、可读性更强,但可能在处理大型数据集时性能略逊于循环迭代方法。

安全建议:

  • 类似于方案一,同样需要注意输入数据的格式和状态值的校验。
  • 对函数式编程方法中的闭包函数进行充分测试,确保其逻辑正确。

总结

本文介绍了两种将二维数组进行透视并对分组值进行计数的方法,并提供了详细的代码示例和操作步骤。 两种方案都能有效解决问题,开发者可以根据实际需求和个人偏好选择合适的方法。循环迭代方式易于理解和实现,而函数式编程方式则更具代码简洁性和可读性。选择哪种方案取决于具体场景和性能要求。在实际应用中,务必对代码进行充分测试,并注意数据安全性和代码的健壮性。