Skip to content

如何避免数组下标越界

「这是我参与11月更文挑战的第3天,活动详情查看:2021最后一次更文挑战

抛出问题

数组下标越界真的是开发过程中的痛,除了在开发过程中各种判断是否设置,是否为空,还有其他优雅的办法解决吗?

回答问题

肯定是有的

举个栗子

比如,我有一个工具性质的方法如下:

我怎么保证 $batchUserCover[$userid]['pickedFootprint']$batchFootprintList[$userid]['list'] 不会有下标越界的问题呢?

php
//批量获得图片故事 优先精选故事 不足三个拼接最近发布的故事     public static function batchImageFootprint($userIds, $batchUserCover, $batchFootprintList)     {         $ret = [];         foreach ($userIds as $userid) {             $ret[$userid] = array_slice(array_merge($batchUserCover[$userid]['pickedFootprint'], array_slice($batchFootprintList[$userid]['list'], 0, 3)), 0, 3);         }         return $ret;     }

解题思路

  1. 在方法外判断是否设置值

  2. 在方法外保证已经设置值,确保 $batchUserCover[$userid]['pickedFootprint'] 这类参数一定是存在的,已经设置了的.

我认为思路2更好

解题实践

实践1:

在传入数据之前,设置好传入值,保证传入值的key必须存在,值可以为null,或者空数组。 核心代码如下:

php
public static function batchFormatCoverAndPickedFootprint($userListInfo)     {         foreach ($userListInfo as &$element) {             $retData[$element['userid']] = [                 'pickedFootprint' => [],                 'coverFootprint' => [],             ];         }                  .         .         .                  return $retData;     }

传入的数组的key必然符合[$userid]['pickedFootprint'],不会存在数组下标越界

ini
$batchUserCover = batchFormatCoverAndPickedFootprint(xxx);     self::batchImageFootprint($userIds, $batchUserCover);

实践2:

和实践1的底层思路是一致的,区别在于实践1是在函数内首先定义了符合规范的初始值

实践2是先处理业务逻辑,在return之前定义了符合规范的初始值

(下面代码段写了注释,重点看后半部分;联合查询那部分代码质量也不错,没省略掉,看能不能抛转引玉。)

php
public static function batchFootprintList($userIds, $pageCount = 21, $batchPickedFootprints = [], $select = 'userid,id,mid,image,text,ST_Astext(picgeom) as "picgeom",poi,poiid,city,province,country,pictime')     {         .         .         .         //联合查询         $union = self::query()->selectRaw($select)->where('userid', $userIds[0])             ->where('status', self::TYPE_STATUS_NORMAL)             ->whereNotIn('mid', $batchPickedFootprints[$userIds[0]])             ->orderBy('id', 'desc')             ->limit($pageCount);         //避免重复查询第一条数据         unset($userIds[0]);         foreach ($userIds as $userId) {             $unionItem = self::query()->selectRaw($select)->where('userid', $userId)                 ->where('status', self::TYPE_STATUS_NORMAL)                 ->whereNotIn('mid', $batchPickedFootprints[$userId])                 ->orderBy('id', 'desc')                 ->limit($pageCount);             $union->unionAll($unionItem);         }         $allUserFootprints = $union->get()->toArray();         $res = [];         $chunkFootprintByUserid = self::_chunkFootprintByUserid($allUserFootprints);                 // 重点在这里         foreach ($allUserIds as $userId) {             $list = $chunkFootprintByUserid[$userId] ?? [];             $count = count($list);             //以此保证不会出现数据下标越界的问题             $res[$userId]['list'] = $list;             $res[$userId]['more'] = $count < $pageCount ? 0 : 1;             $res[$userId]['track'] = $count > 0 ? (string)$list[$count - 1]['id'] : '';         }         return $res;     }

注意

为了行文紧凑,代码段中省略了和文章无关的代码,用竖着的三个.省略。

参与互动

大佬们有啥好的方案欢迎在评论区指教。

🚀 学习遇到瓶颈?想进大厂?

看完这篇技术文章,如果还是觉得不够系统,或者想在实战中快速提升?
王中阳的就业陪跑训练营,提供定制化学习路线 + 企业级实战项目 + 简历优化 + 模拟面试。

了解训练营详情