PHP将所有数组都视为关联数组,因此没有任何内置函数。谁能推荐一种相当有效的方法来检查数组是否“是一个列表”(只包含从0开始的数字键)?
基本上,我希望能够区分这些:
$sequentialArray = [
'apple', 'orange', 'tomato', 'carrot'
];
这:
$assocArray = [
'fruit1' => 'apple',
'fruit2' => 'orange',
'veg1' => 'tomato',
'veg2' => 'carrot'
];
我很惊讶没有人提到array_key_first()
对于您的测试用例:
$sequentialArray = array('apple', 'orange', 'tomato', 'carrot');
$isIndexedArray = is_int( array_key_first($sequentialArray) ); // true
而
$assocArray = array('fruit1' => 'apple',
'fruit2' => 'orange',
'veg1' => 'tomato',
'veg2' => 'carrot');
$isIndexedArray = is_int( array_key_first($assocArray) ); // false
在这里阅读更多关于这个函数的信息。
Mark Amery的改进
function isAssoc($arr)
{
// Is it set, is an array, not empty and keys are not sequentialy numeric from 0
return isset($arr) && is_array($arr) && count($arr)!=0 && array_keys($arr) !== range(0, count($arr) - 1);
}
这个测试变量是否存在,是否为数组,是否为空数组,以及键是否从0开始连续。
来查看数组是否是关联的
if (isAssoc($array)) ...
看看它是不是数值
if (!isAssoc($array)) ...
我认为下面两个函数是最好的方法去检查'如果一个数组是结合或数字'。由于'numeric'可能只表示数字键或顺序数字键,下面列出了两个函数来检查这两种情况:
function is_indexed_array(&$arr) {
for (reset($arr); is_int(key($arr)); next($arr));
return is_null(key($arr));
}
function is_sequential_array(&$arr, $base = 0) {
for (reset($arr), $base = (int) $base; key($arr) === $base++; next($arr));
return is_null(key($arr));
}
The first function checks if each key is an integer value. The second function checks if each key is an integer value and in addition checks if all keys are sequential starting at $base, which defaults to 0 and thus can be omitted if you do not need to specify another base value. key($my_array) returns null if the read pointer is moved past the end of the array, which is what ends the for loop and makes the statement after the for loop return true if all keys were integer. If not, the loop ends prematurely because a key is of type string, and the statement after the for loop will return false. The latter function in addition adds one to $base after each compare, to be able to check if the next key is of the correct value. The strict compare makes it also check if the key is of type integer. The $base = (int) $base part in the first section of the for loop can be left out when $base is omitted or if you make sure it is only called using an integer. But since I can't be sure for everybody, I left it in. The statement is executed only once, anyway. I think these are the most efficient solutions:
Memory wise: No copying of data or key ranges. Doing an array_values or array_keys may seem shorter (less code) but keep in mind what goes on in the background once you make that call. Yes there are more (visible) statements than in some other solutions, but that is not what counts, is it?
Time wise: Besides the fact that copying/extracting data and/or keys also takes time, this solution is more efficient than doing a foreach. Again a foreach may seem more efficient to some because it is shorter in notation, but in the background foreach also calls reset, key and next to do it's looping. But in addition it also calls valid to check the end condition, which is avoided here due to the combination with the integer check.
请记住,数组键只能是整数或字符串,严格的数字字符串,如“1”(但不是“01”)将被转换为整数。如果您希望数组是顺序的,这使得检查整数键成为除了计数之外唯一需要的操作。当然,如果is_indexed_array返回false,则可以将该数组视为关联数组。我说“见过”,因为事实上它们都是。