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

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

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

这:

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

当前回答

解决这个问题的一种方法是利用json_encode,它已经有自己的内部方法来区分关联数组和索引数组,以便输出正确的JSON。

可以通过检查编码后返回的第一个字符是{(关联数组)还是[(索引数组)来做到这一点。

// Too short :)
function is_assoc($arr) {
    ksort($arr);
    return json_encode($arr)[0] === '{';
}

其他回答

除非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 :)

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

function array_is_assoc(array $a) {
    $i = 0;
    foreach ($a as $k => $v) {
        if ($k !== $i++) {
            return true;
        }
    }
    return false;
}

快速、简洁、高效记忆。没有昂贵的比较、函数调用或数组复制。

几天前我又遇到了这个问题,我想利用array_merge特殊属性:

如果输入数组具有相同的字符串键,则该键的后一个值将覆盖前一个值。但是,如果数组包含数字键,则后一个值不会覆盖原始值,而是被追加。输入数组中具有数字键的值将使用结果数组中从0开始的递增键重新编号。 所以为什么不使用:

function Is_Indexed_Arr($arr){
    $arr_copy = $arr;
    if((2*count($arr)) == count(array_merge($arr, $arr_copy))){
        return 1;
    }
    return 0;
}

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

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

已经有很多答案了,下面是Laravel在Arr类中依赖的方法:

/**
 * Determines if an array is associative.
 *
 * An array is "associative" if it doesn't have sequential numerical keys beginning with zero.
 *
 * @param  array  $array
 * @return bool
 */
public static function isAssoc(array $array)
{
    $keys = array_keys($array);

    return array_keys($keys) !== $keys;
}

来源:https://github.com/laravel/framework/blob/5.4/src/Illuminate/Support/Arr.php