按列值对数组行进行分组,并将整行作为子数组推送到组中

Group array rows by column value and push whole rows as subarrays within the group

我的输入是:

$item = [
    ['invoice_id' => '72,', 'item' => 'SN00001'],
    ['invoice_id' => '73,', 'item' => 'SN00002'],
    ['invoice_id' => '73,', 'item' => 'SN00003'],
    ['invoice_id' => '73,', 'item' => 'SN00004'],
    ['invoice_id' => '74,', 'item' => 'SN00005'],
    ['invoice_id' => '74,', 'item' => 'SN00006']
];

我想像这样用 invoice_id 重新分组

[0] => Array
    (
        [invoice_id] => 72
        [group] => Array
            (
                [0] => Array
                    (
                        [invoice_id] => 72,
                        [item] => SN00001
                    )
            )
    )
[1] => Array
    (
        [invoice_id] => 73
        [group] => Array
            (
                [0] => Array
                    (
                        [invoice_id] => 73,
                        [item] => SN00002
                    )
                [1] => Array
                    (
                        [invoice_id] => 73,
                        [item] => SN00003
                    )
                [2] => Array
                    (
                        [invoice_id] => 73,
                        [item] => SN00004
                    )
            )
    )
[2] => Array
    (
        [invoice_id] => 74
        [group] => Array
            (
                [0] => Array
                    (
                        [invoice_id] => 74,
                        [item] => SN00005
                    )
                [1] => Array
                    (
                        [invoice_id] => 74,
                        [item] => SN00006
                    )
            )
    )

这是我目前所做的

$items = [];
foreach($item as $k => $val){
    if(empty($items)){
        // if first row
        $items[$k]['invoice_id'] = $val['invoice_id'];
        $items[$k]['group'] = [$val];
    } else {
        if(!empty($items)){
            foreach($items as $key => $value){
                if($value['invoice_id'] == $val['invoice_id']){
                    // if same invoice_id merge the value into the group
                    $items[$key]['group'] = array_merge($items[$key]['group'], [$val]);
                } else {
                    // else create a array group
                    $items[$k]['invoice_id'] = $val['invoice_id'];
                    $items[$k]['group'] = [$val];
                }
            }
        }
    }
}

样本:https://onecompiler.com/php/3y2hgzk79

我当前代码的问题是,它会在某些组中创建重复项。我试图使用 array_searcharray_column 但它没有达到预期的结果所以我改用 foreach 而我在这里。任何帮助将不胜感激。

这是一个基于一些 built-in PHP 数组处理函数(array_maparray_filterarray_uniquearray_column 的相当简洁的解决方案).它使用 array_columnarray_unique 获取不同 invoice_id 值的列表,然后 array_map 生成输出,根据是否 [=] 过滤每个条目的输入数组19=] 值匹配:

$items = array_map(function ($inv_id) use ($item) {
    return array('invoice_id' => $inv_id,
                 'group' => array_filter($item, 
                                         function ($itm) use ($inv_id) {
                                             return $itm['invoice_id'] == $inv_id;
                                         })
                 );
}, array_unique(array_column($item, 'invoice_id'))
);

输出:

Array
(
    [0] => Array
        (
            [invoice_id] => 72,
            [group] => Array
                (
                    [0] => Array
                        (
                            [invoice_id] => 72,
                            [item] => SN00001
                        )
                )
        )
    [1] => Array
        (
            [invoice_id] => 73,
            [group] => Array
                (
                    [1] => Array
                        (
                            [invoice_id] => 73,
                            [item] => SN00002
                        )
                    [2] => Array
                        (
                            [invoice_id] => 73,
                            [item] => SN00003
                        )
                    [3] => Array
                        (
                            [invoice_id] => 73,
                            [item] => SN00004
                        )
                )
        )
    [4] => Array
        (
            [invoice_id] => 74,
            [group] => Array
                (
                    [4] => Array
                        (
                            [invoice_id] => 74,
                            [item] => SN00005
                        )
                    [5] => Array
                        (
                            [invoice_id] => 74,
                            [item] => SN00006
                        )
                )
        )
)

注意数组内部编号不是从0开始;如果你需要,然后在适当的地方添加 array_values 到 re-index:

$items = array_values(array_map(function ($inv_id) use ($item) {
    return array('invoice_id' => $inv_id,
                 'group' => array_values(array_filter($item, 
                                                      function ($itm) use ($inv_id) { 
                                                          return $itm['invoice_id'] == $inv_id; 
                                                      }))
                 );
}, array_unique(array_column($item, 'invoice_id'))
));

Demo on 3v4l.org

我不知道为什么需要调用 array_filter()array_column()array_search()array_merge()array_unique()。将相关数据分组就是分配临时 first-level 键,然后无条件地声明或将行数据推入组。如果要 re-index 结果数组,只需在循环结束后调用 array_values()

代码:(Demo)

$array = [
    ['invoice_id' => '72,', 'item' => 'SN00001'],
    ['invoice_id' => '73,', 'item' => 'SN00002'],
    ['invoice_id' => '73,', 'item' => 'SN00003'],
    ['invoice_id' => '73,', 'item' => 'SN00004'],
    ['invoice_id' => '74,', 'item' => 'SN00005'],
    ['invoice_id' => '74,', 'item' => 'SN00006']
];

$result = [];
foreach ($array as $row) {
    $result[$row['invoice_id']]['invoice_id'] = $row['invoice_id'];
    $result[$row['invoice_id']]['group'][] = $row;
}

var_export(array_values($result));
// output: exactly as desired in the question