【问题标题】:Group elements from an array with a new element containing group value使用包含组值的新元素对数组中的元素进行分组
【发布时间】:2018-04-26 02:55:08
【问题描述】:

我有一个这样的数组:

$array = [
     ['Categoria' => 'example', 'Servico' => 'name1'],
     ['Categoria' => 'example', 'Servico' => 'name2'],
     ['Categoria' => 'example', 'Servico' => 'name3'],
     ['Categoria' => 'example2', 'Servico' => 'name4'],
     ['Categoria' => 'example2', 'Servico' => 'name5'],
     ['Categoria' => 'example2', 'Servico' => 'name6'],
     ['Categoria' => 'example3', 'Servico' => 'name7'],
     ['Categoria' => 'example3', 'Servico' => 'name8'],
     ['Categoria' => 'example3', 'Servico' => 'name9']
];

我需要将其转换为:

[
    [
        'Servico' => 'example',
        'children' => [
            ['Servico' => 'name1'],
            ['Servico' => 'name2'],
            ['Servico' => 'name3'],
        ]
    ],
    [
        'Servico' => 'example2',
        'children' => [
            ['Servico' => 'name4'],
            ['Servico' => 'name5'],
            ['Servico' => 'name6'],
        ]
    ],
    [
        'Servico' => 'example3',
        'children' => [
            ['Servico' => 'name7'],
            ['Servico' => 'name8'],
            ['Servico' => 'name9'],
        ]
    ],
]

我已阅读 this topic 并成功地对数组进行了分组,但我无法找到一种方法来格式化数组,使其在每个对象上都有 Servicochildren

有人有什么想法吗?

【问题讨论】:

  • 等等...你怎么能在同一个数组中有几个同名的键?
  • @Andreas,我有一个带有 Servicofaher,它的所有 children 也必须有 Servico 作为键。我不认为这会是个问题。

标签: php arrays multidimensional-array grouping


【解决方案1】:

您可以 foreach 数组并使用您想要的结构构建一个新数组。

$new =array();
Foreach($A as $item){
    If(!isset($new[$item['Categoria']])) $new[$item['Categoria']] = array(); // create array of not set
    $new[$item['Categoria']][] = $item['Servico']; // add servico item to array
}

如果找不到将创建它的子数组,则会循环每个项目。
然后在子数组中添加“名称”值。

编辑,现在看到您希望将输出数组命名为 B,只需将代码中的“new”更改为“B”即可。

【讨论】:

  • 这可行,但它不会将键的名称放在每个对象上,例如Servicochildren。我怎么能这样做?
【解决方案2】:

假设 $array 是你的数组

$i=0;
$temp = array();
foreach ($array as $arr)
{
    if($i !=0 && $arr['Categoria'] == $temp[$i-1]['Servico']){
        $temp[$i-1]['children']['Servico'] = $arr['Servico'];
    }else{
        $temp[$i]['Servico'] =$arr['Categoria'];
        $temp[$i]['children']['Servico'] = $arr['Servico'];
        $i++;
    }
}
//$temp is your new array

【讨论】:

  • 此方法不会读取整个数组。每个元素只返回一个子元素。
【解决方案3】:

这里不需要多个循环、条件或计数器。

每个组的 Servico 值 ($row['Categoria']) 可以在每次迭代时安全地被覆盖。

每个新的$row['Servico'] 值都将无条件地推入相应的children 子数组中。

使用$row['Categoria']在结果数组中提供临时分组键后,使用array_values()重新索引结果。

*注意:我选择将children 的数据结构展平为索引数组。我看不到为每个条目创建单元素关联数组的任何价值。如果您确实需要,请将['Servico' => $row['Servico']] 推入children

带有array_reduce()的函数式:(Demo)

var_export(
    array_values(
        array_reduce(
            $array,
            function ($carry, $row) {
                $carry[$row['Categoria']]['Servico'] = $row['Categoria'];
                $carry[$row['Categoria']]['children'][] = $row['Servico'];
                return $carry;
            }
        )
    )
);

经典foreach(): (Demo)

$result = [];
foreach ($array as $row) {
    $result[$row['Categoria']]['Servico'] = $row['Categoria'];
    $result[$row['Categoria']]['children'][] = $row['Servico'];
}
var_export(array_values($result));

【讨论】:

  • 这个太完美了!但是我在玩你的代码,我做了类似that 的事情,唯一的问题是每个数组的索引是Servico 的名称,而不是数字,就像你的例子一样。你知道我可以改变什么来达到你的结果吗?
  • 没有。不幸的是,您将无法在一个 foreach 循环中的两个级别上使用 php 的自动数组索引。我确信这个过程可以在一个循环中完成,但是你会失去自动索引(你必须使用计数器并有条件地增加它们——创建了复杂的代码)。在这种情况下,我推荐两个循环。
  • 我就是这么想的。然后我将使用两个循环。非常感谢您的回答。问题解决了!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-06-07
  • 1970-01-01
  • 2023-03-22
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多