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

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

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

这:

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

当前回答

function isAssoc($arr)
{
    $a = array_keys($arr);
    for($i = 0, $t = count($a); $i < $t; $i++)
    {
        if($a[$i] != $i)
        {
            return false;
        }
    }
    return true;
}

其他回答

这个函数可以处理:

索引有孔的数组(例如1、2、4、5、8、10) 带有“0x”键的数组:例如,键“08”是关联的,键“8”是顺序的。

思想很简单:如果其中一个键不是整数,它就是关联数组,否则就是顺序数组。

function is_asso($a){
    foreach(array_keys($a) as $key) {if (!is_int($key)) return TRUE;}
    return FALSE;
}

检测关联数组(哈希数组)的最佳函数

<?php
function is_assoc($arr) { return (array_values($arr) !== $arr); }
?>

检查数组是否有所有的关联键。使用stdClass & get_object_vars ^):

$assocArray = array('fruit1' => 'apple', 
                    'fruit2' => 'orange', 
                    'veg1' => 'tomato', 
                    'veg2' => 'carrot');

$assoc_object = (object) $assocArray;
$isAssoc = (count($assocArray) === count (get_object_vars($assoc_object)));  
var_dump($isAssoc); // true

为什么?函数get_object_vars只返回可访问的属性(请参阅在将数组转换为对象期间发生的更多信息)。然后,只是逻辑上:如果基本数组元素的计数等于对象的可访问属性的计数-所有键都是关联的。

一些测试:

$assocArray = array('apple', 'orange', 'tomato', 'carrot');
$assoc_object = (object) $assocArray; 
$isAssoc = (count($assocArray) === count (get_object_vars($assoc_object)));
var_dump($isAssoc); // false 
//...

$assocArray = array( 0 => 'apple', 'orange', 'tomato', '4' => 'carrot');
$assoc_object = (object) $assocArray; 
$isAssoc = (count($assocArray) === count (get_object_vars($assoc_object)));
var_dump($isAssoc); // false 

//... 
$assocArray = array('fruit1' => 'apple', 
                    NULL => 'orange', 
                    'veg1' => 'tomato', 
                    'veg2' => 'carrot');

$assoc_object = (object) $assocArray;
$isAssoc = (count($assocArray) === count (get_object_vars($assoc_object)));  
var_dump($isAssoc); //false

Etc.

function isAssoc($arr)
{
    $a = array_keys($arr);
    for($i = 0, $t = count($a); $i < $t; $i++)
    {
        if($a[$i] != $i)
        {
            return false;
        }
    }
    return true;
}

答案已经给出了,但关于表现的虚假信息太多了。 我写了这个小的基准测试脚本,它显示foreach方法是最快的。

免责声明:以下方法是从其他答案复制粘贴的

<?php

function method_1(Array &$arr) {
    return $arr === array_values($arr);
}

function method_2(Array &$arr) {
    for (reset($arr), $i = 0; key($arr) !== $i++; next($arr));
    return is_null(key($arr));
}

function method_3(Array &$arr) {
    return array_keys($arr) === range(0, count($arr) - 1);
}

function method_4(Array &$arr) {
    $idx = 0;
    foreach( $arr as $key => $val ){
        if( $key !== $idx )
            return FALSE;
        $idx++;
    }
    return TRUE;
}




function benchmark(Array $methods, Array &$target){    
    foreach($methods as $method){
        $start = microtime(true);
        for ($i = 0; $i < 1000; $i++)
            $dummy = call_user_func($method, $target);

        $end = microtime(true);
        echo "Time taken with $method = ".round(($end-$start)*1000.0,3)."ms\n";
    }
}



$targets = [
    'Huge array' => range(0, 30000),
    'Small array' => range(0, 1000),
];
$methods = [
    'method_1',
    'method_2',
    'method_3',
    'method_4',
];
foreach($targets as $targetName => $target){
    echo "==== Benchmark using $targetName ====\n";
    benchmark($methods, $target);
    echo "\n";
}

结果:

==== Benchmark using Huge array ====
Time taken with method_1 = 5504.632ms
Time taken with method_2 = 4509.445ms
Time taken with method_3 = 8614.883ms
Time taken with method_4 = 2720.934ms

==== Benchmark using Small array ====
Time taken with method_1 = 77.159ms
Time taken with method_2 = 130.03ms
Time taken with method_3 = 160.866ms
Time taken with method_4 = 69.946ms