使用 foreach 循环的自定义格式数组 - PHP

问题描述

我试图格式化一个数组,如果它没有特定的 id,我试图将数据分配为 0。但它没有发生。

这里我面临的问题是,当我尝试添加 $dataset[$label['id']]['data'][] = 0 时,如果它为空或未在主数组 $array标签对象中找到,它不起作用。

我有以下数组:

$array = '[{
        "id": 26,"name": "Tactical","count": 127,"labels": {
            "2": {
                "id": 2,"risk": "Medium","count": 80
            },"1": {
                "id": 1,"risk": "Low","count": 39
            },"3": {
                "id": 3,"risk": "High","count": 8
            }
        }
    },{
        "id": 14,"name": "Citizen Safety","count": 116,"labels": {
            "4": {
                "id": 4,"risk": "Extreme","count": 7
            },"2": {
                "id": 2,"count": 103
            },"count": 6
            }
        }
    },{
        "id": 25,"name": "Strategic","count": 79,"count": 40
            },"count": 11
            },"count": 28
            }
        }
    }
]';

这是我正在尝试的代码片段

$labels = [];
$dataset = [];
    
foreach ($array as $key => $value) {
    $labels[] = $value['name'];
    foreach ($value['labels'] as $label) {
        if (empty($dataset[$label['id']])) {
            $dataset[$label['id']] = [
                'label' => $label['risk'],'backgroundColor' => '#FF9534'
            ];
            $dataset[$label['id']]['data'] = [];
            $dataset[$label['id']]['data'][] = $label['count'];
        } else {
            if (empty($dataset[$label['id']]['data'])) {
                $dataset[$label['id']]['data'][] = 0;
            } else {
                $dataset[$label['id']]['data'][] = $label['count'];
            }
        }
    }
}
    
$dataset = [
    'labels' => $labels,'datasets' => $dataset,];
    
echo json_encode($dataset);
die;

我得到以下输出

{
    "labels": [
        "Tactical","Citizen Safety","Strategic"
    ],"datasets": {
        "2": {
            "label": "Medium","backgroundColor": "#FF9534","data": [
                80,103,40
            ]
        },"1": {
            "label": "Low","data": [
                39,11
            ]
        },"3": {
            "label": "High","data": [
                8,6,28
            ]
        },"4": {
            "label": "Extreme","data": [
                7
            ]
        }
    }
}

但我想要的实际输出是下面的

{
    "labels": [
        "Tactical","data": [
                0,7,0
            ]
        }
    }
}

我的意思是当我循环遍历 $array 数组对象的标签时,当任何数组对象没有标签对象(如中、低、高、极端)时,我试图将计数分配为 0这在响应中没有发生。有人可以帮我解决在这里缺少的东西吗? 您可以在此处检查代码的执行情况https://sandbox.onlinephpfunctions.com/code/398b2d1aa892e898a72fb053e981519e3215a053

请找到下面的图像以了解输出的差异

enter image description here

解决方法

让我们以数组中的第二个元素为例,它看起来像这样

'labels' => 
        array (size=3)
          4 => 
            array (size=3)
              'id' => int 4
              'risk' => string 'Extreme' (length=7)
              'count' => int 7
          2 => 
            array (size=3)
              'id' => int 2
              'risk' => string 'Medium' (length=6)
              'count' => int 103
          3 => 
            array (size=3)
              'id' => int 3
              'risk' => string 'High' (length=4)
              'count' => int 6

对于这个元素,您希望结果数组包含一个 0,用于标签 Low (id is 1)。为了创建结果集,您需要使用 {{ 1}} 并使用 foreach ($value['labels'] as $label)

为数据赋值

到目前为止一切都很好。但是,请注意,当 php 迭代这个数组时,它只有 3 个键,即。 $dataset[$label['id']]['data'][] = $label['count'];。它正确填充结果数组。

现在我们还期望它为 id 4,2 & 3 填充计数,该计数甚至不存在于该数组中,并且在特定迭代中从未遇到过。因此,赋值行 1 中的变量 $label['id'] 永远不会等于 1

您可以通过在每个数组中插入计数为 0 的缺失元素来解决此问题。

为了做到这一点,我们需要一个所有风险标签的列表,并以它们的 id 作为关键字。我们可以使用 $dataset[$label['id']]['data'][] = $label['count'];array_column 来做到这一点。

请注意 array_merge_recursive 中的 array_merge_recursive。这称为 splat 运算符,用于 ... 数组。 You can read more about splat on this questions

unpack

一旦我们有了所有风险的列表,我们需要做的就是遍历 $riskArray = array_column($array,'labels'); $riskArrayFiltered = array_column(array_merge_recursive(...$riskArray),'risk','id'); ,检查并添加任何缺失的风险标签。

$array

现在你可以在这个数组上运行你的代码来得到你正在寻找的东西。

我确实建议您在创建时尝试更改数组的结构。应该有一种更简单、更简洁的方法来完成您正在尝试做的事情。

Here is a working example