PHP把一个具有重复元素的数组拼装进去另外一个数组

默认分类 PHP Array

今天遇到了一个问题记录一下,遇到同样困难的朋友可参考一下,现有一个数组A,另外有一个数组B,大体结构如下.

数组内容

大体如下,简单记一下,实际情况比这多得多.根据'serial_number'来组装数组,A中的'serial_number'是唯一值.

     $A = [
            [
                'id' => '12',
                'serial_number' => 'Y2011020001',
                'finish' => '2020-11-02 13:00:00',
                'ratio_number' => 'S35X-R3',
            ],
            [
                'id' => '13',
                'serial_number' => 'Y2011020002',
                'finish' => '2020-11-02 13:00:00',
                'ratio_number' => 'S35X-R3',
            ],
            [
                'id' => '14',
                'serial_number' => 'Y2011020003',
                'finish' => '2020-11-02 13:00:00',
                'ratio_number' => 'S35X-R3',
            ],
            [
                'id' => '15',
                'serial_number' => 'Y2011020004',
                'finish' => '2020-11-02 13:00:00',
                'ratio_number' => 'S35X-R3',
            ],
        ];


     $B = [
            [
                'id' => '112',
                'serial_number' => 'Y2011020001',
                'card' => '2020-11-02 13:00:00',
                'st' => 'EXSSEX',
            ],
            [
                'id' => '113',
                'serial_number' => 'Y2011020001',
                'card' => '2020-11-02 13:00:00',
                'st' => 'EXSSEX',
            ],
            [
                'id' => '114',
                'serial_number' => 'Y2011020001',
                'card' => '2020-11-02 13:00:00',
                'st' => 'EXSSEX',
            ],
            [
                'id' => '115',
                'serial_number' => 'Y2011020004',
                'card' => '2020-11-02 13:00:00',
                'st' => 'EXSSEX',
            ],
        ];

需求

寻找B数组所有'serial_number'与A数组的'serial_number'相同的,并把数据插进去,以上面为例,最终效果如下:

        $A = [
            [
                'id'            => '12',
                'serial_number' => 'Y2011020001',
                'finish'        => '2020-11-02 13:00:00',
                'ratio_number'  => 'S35X-R3',
                'child'         => [
                    [
                        'id'            => '112',
                        'serial_number' => 'Y2011020001',
                        'card'          => '2020-11-02 13:00:00',
                        'st'            => 'EXSSEX',
                    ],
                    [
                        'id'            => '113',
                        'serial_number' => 'Y2011020001',
                        'card'          => '2020-11-02 13:00:00',
                        'st'            => 'EXSSEX',
                    ],
                    [
                        'id'            => '114',
                        'serial_number' => 'Y2011020001',
                        'card'          => '2020-11-02 13:00:00',
                        'st'            => 'EXSSEX',
                    ],
                ],
            ],
            [
                'id'            => '13',
                'serial_number' => 'Y2011020002',
                'finish'        => '2020-11-02 13:00:00',
                'ratio_number'  => 'S35X-R3',
                'child'         => [],
            ],
            [
                'id'            => '14',
                'serial_number' => 'Y2011020003',
                'finish'        => '2020-11-02 13:00:00',
                'ratio_number'  => 'S35X-R3',
                'child'         => [],
            ],
            [
                'id'            => '15',
                'serial_number' => 'Y2011020004',
                'finish'        => '2020-11-02 13:00:00',
                'ratio_number'  => 'S35X-R3',
                'child'         => [
                    [
                        'id'            => '115',
                        'serial_number' => 'Y2011020004',
                        'card'          => '2020-11-02 13:00:00',
                        'st'            => 'EXSSEX',
                    ],
                ],
            ],
        ];

思路

处理数组,最先想到的肯定是foreach来处理,少的话肯定没问题,但是实际中A数组与B数组各有1000个元素,总循环就要1000*1000次循环了,如果A和B各有1万,就要1亿次循环,而且直接用foreach感觉不爽,想做一些骚操作,就想别的处理方法.

首先肯定要先foreach A的,然后带着A的值去找B.

B中有重复的,并且还要取出来组成数组装进对应的A中.网络上找了一些资料,就二分法的启发有点作用.

B中的serial_number虽然有重复,但是按顺序排列的,最开始我想的是可以生成一种类似于地图映射这种减少循环范围.
先count出有多少元素,然后在B数组的5/1, 5/2, 5/3, 5/4, 5/5的位置取'serial_number'值,然后forea A的时候,判断A的'serial_number'值大体在数组的那个位置,直接for B的那个区间去拼装A.

再后来我想到,用array_search()方法,直接定位到开始key的位置往后面循环,到不同的元素就break出来.

最后我用了array_keys方法,这个可以返回指定值在数组中的所有key.所以直接提出来B的serial_number,然后找到键名直接装进去.实现效果如下

实现

//直接取出B中所有的serial_number,它的key是和原数组的key对应的
$b_serial_array = array_column($B, 'serial_number');
foreach ($A as $key => $value) {
    $A[$key]['child'] = [];
    //获取当前serial_number在B数组中所有的key.
    $key_array = array_keys($b_serial_array, $value['serial_number']);
    //如果未获取到就说明没有,进行下次循环
    if (empty($key_array)) continue;
    //不为空就循环组装进去A数组
    foreach ($key_array as $k) {
        $A[$key]['child'][] = $B[$k];
    }
}

return $A;

至此结束.

新评论

称呼不能为空
邮箱格式不合法
网站格式不合法
内容不能为空