按共享子数组值对多维数组中的数据集进行分组,并将累积值推送到组的列中

Group data sets in a multidimensional array by a shared subarray value and push accumulated values into a column of the group

提问人:Chris C 提问时间:11/2/2023 最后编辑:mickmackusaChris C 更新时间:11/11/2023 访问量:71

问:

我正在使用 PHP,我有以下数组,并且一直在尝试弄清楚如何以以下方式将其扁平化。这是一个使用 json_decode 从 JSON 创建的数组,最终结果将是另一个 JSON 文件。

因此,无论我们在哪里有一个唯一的名称,在父数组的每个元素中,和 将始终相同。我需要一种方法来基本上“折叠”数组并组合数组,同时向操作数组添加新元素。patternTypetype

当前数据结构。

[
    'abc' => [
        [
            'foo' => '*',
            'action' => 'Read',
            'resource' => [
                'name' => 'name_1',
                'patternType' => 'fixed',
                'type' => 'partition',
            ],
        ],
        [
            'foo' => '*',
            'action' => 'Write',
            'resource' => [
                'name' => 'name_1',
                'patternType' => 'fixed',
                'type' => 'partition',
            ],
        ],
        [
            'foo' => '*',
            'action' => 'Read',
            'resource' => [
                'name' => 'name_2',
                'patternType' => 'fixed',
                'type' => 'partition',
            ],
        ],
        [
            'foo' => '*',
            'action' => 'Alter',
            'resource' => [
                'name' => 'name_2',
                'patternType' => 'fixed',
                'type' => 'partition',
            ],
        ],
    ],
];

所需的数据结构

Array
(
    [abc] => Array
            [0] => Array
                (
                    [foo] => *
                    [action] => Array
                        (
                            [0] => Read
                            [1] => Write
                        )
                    [resource] => Array
                        (
                            [name] => name_1
                            [patternType] => fixed
                            [type] => partition
                        )

                )
            [1] => Array
                (
                    [foo] => *
                    [action] => Array
                        (
                            [0] => Read
                            [1] => Alter
                        )
                    [resource] => Array
                        (
                            [name] => name_2
                            [patternType] => fixed
                            [type] => partition
                        )

                )
)

我尝试了各种功能,如array_merges、array_merge_recursive等......我还尝试遍历数组,并创建一个辅助数组并在那里正确创建数据结构,但我总是遇到一个问题,即在这种情况下如何引用父数组,b/c 子数组的顺序总是不同的。

PHP 维数组 分组

评论


答:

-2赞 Anis Hamal 11/2/2023 #1

这是适合您的解决方案

<?php
$array = [
    "abc" => [
        [
                    "foo" => "*",
                    "action" => "Read",
                    "resource" => [
                            "name" => "name_1",
                            "patternType" => "fixed",
                            "type" => "partition"
                        ]

        ],
        [
                    "foo" => "*",
                    "action" => "Write",
                    "resource" => [
                            "name" => "name_1",
                            "patternType" => "fixed",
                            "type" => "partition"
                        ]

        ],
        [
                    "foo" => "*",
                    "action" => "Read",
                    "resource" => [
                            "name" => "name_2",
                            "patternType" => "fixed",
                            "type" => "partition"
                        ]

        ],
         [
                    "foo" => "*",
                    "action" => "Alter",
                    "resource" => [
                            "name" => "name_2",
                            "patternType" => "fixed",
                            "type" => "partition"
                        ]


        ],
    ]
    
];

$grouparr = [];
$tempVal;
$action;



foreach ($array['abc'] as $key => $val) {
   if (isset($tempVal['resource']['name']) && ($val['resource']['name'] == $tempVal['resource']['name'])){
    $grouparr[$key] = $val;
    $actions = [$action];
    array_push($actions, $grouparr[$key]['action']);
    $grouparr[$key]['action'] = $actions;

   } else {
     $action = $val['action'];
     $tempVal = $val;
   }
      
 }

print_r(array_values($grouparr));

?>

评论

1赞 mickmackusa 11/2/2023
我们不应该看到任何现代 PHP 脚本依赖于 be quiet 运算符 ()。此外,从来没有充分的理由在 Stack Overflow 上发布纯代码答案——每个答案都应该包括一个简单的英语解释,目的是教育和授权。@
-2赞 Web Marketing Solution Network 11/2/2023 #2

为了实现所需的数据结构,您可以遍历原始数组并使用临时关联数组按“name”字段对元素进行分组。然后,您可以从此临时数组创建所需的结构。下面是一个PHP代码示例:

$outputArray = [];

foreach ($inputArray as $key => $items) {
    $tempArray = [];

    foreach ($items as $item) {
        $name = $item['resource']['name'];

        if (!isset($tempArray[$name])) {
            $tempArray[$name] = [
                'foo' => $item['foo'],
                'action' => [],
                'resource' => $item['resource'],
            ];
        }

        $tempArray[$name]['action'][] = $item['action'];
    }

    $outputArray[$key] = array_values($tempArray);
}
echo "<pre>";
print_r($outputArray);

这将在 中为您提供所需的数据结构。$outputArray

1赞 mickmackusa 11/2/2023 #3

通过在结果数组中推送引用变量,可以避免清除不需要的键。这是一种更直接的方法。array_values()

我认为“资源名称”是识别数据集唯一性的可靠方法。通过此标识符声明引用变量。

如果以前没有遇到过标识符,请将该值强制转换为孤元素数组,定义引用变量的数据,然后推入结果数组。如果之前遇到过标识符,只需将新值推送到引用的子数组中即可。actionactionaction

代码:(演示)

$result = [];
foreach ($array as $key => $sets) {
    foreach ($sets as $set) {
        $id = $set['resource']['name'];
        if (!isset($ref[$id])) {
            $set['action'] = (array) $set['action'];
            $ref[$id] = $set;
            $result[$key][] = &$ref[$id];
        } else {
            $ref[$id]['action'][] = $set['action'];
        }
    }
}
var_export($result);

或者,如果您只想改变输入数组而不生成新数组,请调整引用以指向给定值的第一个遇到集合的子数组。actionname

代码:(演示)

foreach ($array as $key => &$sets) {
    foreach ($sets as $i => &$set) {
        $id = $set['resource']['name'];
        if (!isset($ref[$id])) {
            $set['action'] = (array) $set['action'];
            $ref[$id] = &$set['action'];
        } else {
            $ref[$id][] = $set['action'];
            unset($array[$key][$i]);
        }
    }
}
var_export($array);