在PHP项目开发中数组是经常操作的数据类型,不过没想到的是今天居然在二维数组转一维数组的操作中翻了船。好在仔细检查之后都解决了。下面就将二维数组转一维数组的两种方法分享一下,以及避免再次入坑。
一、需求:
转换前的二维数组格式。
- array(2) { [0]=> array(7) { ["id"]=> string(2) "46" ["goods_id"]=> string(5) "77433" ["model_name"]=> string(6) "颜色" ["model_sub_name"]=> array(4) { [0]=> string(6) "黑色" [1]=> string(6) "肤色" [2]=> string(6) "粉色" [3]=> string(9) "浅蓝色" } ["goods_stock"]=> array(1) { [0]=> string(3) "254" } ["curr_price"]=> array(1) { [0]=> string(4) "31.5" } ["goods_weight"]=> array(1) { [0]=> string(3) "280" } } [1]=> array(7) { ["id"]=> string(2) "47" ["goods_id"]=> string(5) "77433" ["model_name"]=> string(6) "尺码" ["model_sub_name"]=> array(4) { [0]=> string(1) "S" [1]=> string(1) "M" [2]=> string(1) "L" [3]=> string(2) "XL" } ["goods_stock"]=> array(1) { [0]=> string(3) "254" } ["curr_price"]=> array(1) { [0]=> string(4) "31.5" } ["goods_weight"]=> array(1) { [0]=> string(3) "280" } } }
转换后的数组格式:
- array(8) { [0]=> array(5) { ["model_name"]=> string(6) "颜色" ["model_sub_name"]=> string(6) "黑色" ["goods_stock"]=> string(3) "254" ["curr_price"]=> string(4) "31.5" ["goods_weight"]=> string(3) "280" } [1]=> array(5) { ["model_name"]=> string(6) "颜色" ["model_sub_name"]=> string(6) "肤色" ["goods_stock"]=> string(3) "254" ["curr_price"]=> string(4) "31.5" ["goods_weight"]=> string(3) "280" } [2]=> array(5) { ["model_name"]=> string(6) "颜色" ["model_sub_name"]=> string(6) "粉色" ["goods_stock"]=> string(3) "254" ["curr_price"]=> string(4) "31.5" ["goods_weight"]=> string(3) "280" } [3]=> array(5) { ["model_name"]=> string(6) "颜色" ["model_sub_name"]=> string(9) "浅蓝色" ["goods_stock"]=> string(3) "254" ["curr_price"]=> string(4) "31.5" ["goods_weight"]=> string(3) "280" } [4]=> array(5) { ["model_name"]=> string(6) "尺码" ["model_sub_name"]=> string(1) "S" ["goods_stock"]=> string(3) "254" ["curr_price"]=> string(4) "31.5" ["goods_weight"]=> string(3) "280" } [5]=> array(5) { ["model_name"]=> string(6) "尺码" ["model_sub_name"]=> string(1) "M" ["goods_stock"]=> string(3) "254" ["curr_price"]=> string(4) "31.5" ["goods_weight"]=> string(3) "280" } [6]=> array(5) { ["model_name"]=> string(6) "尺码" ["model_sub_name"]=> string(1) "L" ["goods_stock"]=> string(3) "254" ["curr_price"]=> string(4) "31.5" ["goods_weight"]=> string(3) "280" } [7]=> array(5) { ["model_name"]=> string(6) "尺码" ["model_sub_name"]=> string(2) "XL" ["goods_stock"]=> string(3) "254" ["curr_price"]=> string(4) "31.5" ["goods_weight"]=> string(3) "280" } }
这种格式看起来可能比较乱,但是适合复制测试。其中model_sub_name、goods_stock、curr_price、goods_weight都是数组格式,如果goods_stock、curr_price、goods_weight数组只有一个元素的时候,不同的model_sub_name对应的都是这一个元素,如果元素大于1,那么就需要model_sub_name下标所对应的goods_stock、curr_price、goods_weight值作为新数组的相关键值。
解决方法:
方法一、foreach循环,或for循环都行。就贴一个foreach吧。
- $model = array();
- foreach($guige as $key=>$value){
- foreach($value['model_sub_name'] as $k=>$v){
- $model[$t]['model_name'] = $value['model_name'];
- $model[$t]['model_sub_name'] = $v;
- $model[$t]['goods_stock'] = sizeof($value['goods_stock'])>1?$value['goods_stock'][$k]:$value['goods_stock'][0];
- $model[$t]['curr_price'] = sizeof($value['curr_price'])>1?$value['curr_price'][$k]:$value['curr_price'][0];
- $model[$t]['goods_weight'] = sizeof($value['goods_weight'])>1?$value['goods_weight'][$k]:$value['goods_weight'][0];
- $t +=1 ;
- }
- }
方法二、reduce。(来自“原罪”的分享)
- $result = array_reduce($guige, function ($carry, $item) {
- $extraProperties = ['goods_stock', 'curr_price', 'goods_weight'];
- // 先计算下标数量,提高效率
- $lengths = [];
- foreach ($extraProperties as $property) {
- $lengths[$property] = count($item[$property]) - 1;
- }
- // 开始收集
- foreach ($item['model_sub_name'] as $index => $subName) {
- $sub = [
- 'model_name' => $item['model_name'],
- 'model_sub_name' => $subName,
- ];
- foreach ($extraProperties as $property) {
- $sub[$property] = $item[$property][min($index, $lengths[$property])];
- }
- $carry[] = $sub;
- }
- return $carry;
- }, []);
在这里遇到的一个坑是我用方法一解决问题的时候,$t = $key+$k导致了部分数据被覆盖的问题,所以循环结果的一维数组值不全。所以将这次填坑过程写出来,希望可以帮助其他需要的小伙伴们。