PHP将所有数组都视为关联数组,因此没有任何内置函数。谁能推荐一种相当有效的方法来检查数组是否“是一个列表”(只包含从0开始的数字键)?

基本上,我希望能够区分这些:

$sequentialArray = [
    'apple', 'orange', 'tomato', 'carrot'
];

这:

$assocArray = [
    'fruit1' => 'apple',
    'fruit2' => 'orange',
    'veg1' => 'tomato',
    'veg2' => 'carrot'
];

当前回答

当然,这是一个更好的选择。

<?php
$arr = array(1,2,3,4);
$isIndexed = array_values($arr) === $arr;

其他回答

除非PHP有这样的内置功能,否则您无法在小于O(n)的时间内完成—枚举所有键并检查整数类型。事实上,你还想确保没有漏洞,所以你的算法可能是这样的:

for i in 0 to len(your_array):
    if not defined(your-array[i]):
        # this is not an array array, it's an associative array :)

但为什么要麻烦呢?只需假设数组是您所期望的类型。如果不是,它就会在你面前爆炸——这就是动态编程!测试你的代码,一切都会很好……

简单地说,你可以通过以下步骤检查数组是否关联

使用array_keys()将数组的所有键转换为一个数组 使用array_filter()和从数组中过滤非数字键 is_numeric () 比较过滤数组和实际数组中的元素数量,如果两个数组中的元素数量不相等,则为关联数组。

以上步骤的功能如下所示。

 function isAssociative(array $array)
    {
        return count(array_filter(array_keys($array), function($v){return is_numeric($v);})) !== count($array));
    }

修改最流行的答案。 这需要更多的处理,但更准确。

<?php
//$a is a subset of $b
function isSubset($a, $b)
{
    foreach($a =>$v)
        if(array_search($v, $b) === false)
            return false;

    return true;

    //less effecient, clearer implementation. (uses === for comparison)
    //return array_intersect($a, $b) === $a;
}

function isAssoc($arr)
{
    return !isSubset(array_keys($arr), range(0, count($arr) - 1));
}

var_dump(isAssoc(array('a', 'b', 'c'))); // false
var_dump(isAssoc(array(1 => 'a', 0 => 'b', 2 => 'c'))); // false
var_dump(isAssoc(array("0" => 'a', "1" => 'b', "2" => 'c'))); // false 
//(use === in isSubset to get 'true' for above statement)
var_dump(isAssoc(array("a" => 'a', "b" => 'b', "c" => 'c'))); // true
?>

仅仅检查数组是否有非整数键(而不是数组是否按顺序索引或零索引):

function has_string_keys(array $array) {
  return count(array_filter(array_keys($array), 'is_string')) > 0;
}

如果至少有一个字符串键,$array将被视为一个关联数组。

如果你只是寻找非数字键(无论顺序),那么你可能想尝试一下

function IsAssociative($array)
{
    return preg_match('/[a-z]/i', implode(array_keys($array)));
}