如何在PHP中区分索引数组与含连续键的关联数组
区分PHP普通索引数组与手动指定连续整数键的关联数组
我使用Laravel 10搭配Livewire v3,现有一个接收数组作为参数的方法,需要根据传入的是普通索引数组还是**关联数组(包括键为连续整数的关联数组)**执行不同逻辑。当前的判断逻辑会将手动指定连续整数键的$associative_sequential数组识别为索引数组,我需要修改逻辑,使其将该数组判定为关联数组,同时不能将普通索引数组误判为关联数组。
现有代码
public function doSomething($passedArray) { if (is_array($passedArray)) { if ($passedArray == array_values($passedArray)) { echo "The passed array is a sequential array.\n"; } elseif (array_keys($passedArray) == array_filter(array_keys($passedArray), 'is_int')) { echo "The passed array is an associative array with integer keys.\n"; } else { echo "The passed array is an associative array with non-integer keys.\n"; } } else { echo "The passed variable is not an array.\n"; } } $sequential = array("apple", "banana", "cherry"); $associative_sequential = array(0 => "apple", 1 => "banana", 2 => "cherry"); $associative_non_sequential = array(10 => "apple", 20 => "banana", 25 => "cherry"); $strict_associative = array("fruit1" => "apple", "fruit2" => "banana", "fruit3" => "cherry"); doSomething($sequential); doSomething($associative_sequential); doSomething($associative_non_sequential); doSomething($strict_associative);
当前输出
// This is what I am getting The passed array is a sequential array. The passed array is a sequential array. The passed array is an associative array with integer keys. The passed array is an associative array with non-integer keys.
期望输出
// This is what I want to happen The passed array is a sequential array. The passed array is an associative array with integer keys. The passed array is an associative array with integer keys. The passed array is an associative array with non-integer keys.
问题分析与解决方案
首先明确:PHP中没有本质上的索引数组和关联数组之分,所有数组都是有序映射结构。手动指定连续整数键的数组(如$associative_sequential)和自动生成键的普通索引数组(如$sequential)在底层完全等价,使用==或===比较都会返回true,因此无法直接通过数组本身的结构区分两者。
如果一定要实现你的期望逻辑,只能通过自定义规则或额外标记来区分:
方案1:添加自定义类型标记
在传递数组时,额外加入一个标记键来标识数组类型,方法中先判断该标记:
public function doSomething($passedArray) { if (is_array($passedArray)) { // 读取并移除标记键 $isAssociative = isset($passedArray['_is_associative']) ? $passedArray['_is_associative'] : false; unset($passedArray['_is_associative']); if (!$isAssociative && $passedArray === array_values($passedArray)) { echo "The passed array is a sequential array.\n"; } elseif (array_keys($passedArray) == array_filter(array_keys($passedArray), 'is_int')) { echo "The passed array is an associative array with integer keys.\n"; } else { echo "The passed array is an associative array with non-integer keys.\n"; } } else { echo "The passed variable is not an array.\n"; } } // 调用时给需要标记的数组添加标记 $associative_sequential = array(0 => "apple", 1 => "banana", 2 => "cherry", '_is_associative' => true);
方案2:调整业务逻辑定义
如果允许调整判断规则,可以将索引数组限定为「仅通过无键声明方式创建的数组」,比如["apple", "banana"],而所有手动指定键的数组(哪怕是连续整数)都归为关联数组。这种方式需要依赖业务场景中数组的生成来源,比如explode()返回的数组视为索引数组,array_combine()或手动指定键的数组视为关联数组。
说明
如果业务场景必须严格区分这两种数组,最可靠的方式是使用方案1(添加类型标记),因为PHP本身无法区分手动指定连续整数键的数组和自动生成键的索引数组。
内容的提问来源于stack exchange,提问作者VoidOfLimbo
相关产品推荐
相关产品推荐

