区分关联数组和普通数组

3

如果给定一个关联数组而不是普通数组,我希望一个PHP函数在不改变函数签名的情况下表现得不同。

注意:您可以假设数组是同质的。例如,array(1,2,"foo" => "bar")是不被接受的,可以忽略。

function my_func(Array $foo){
  if (…) {
    echo "Found associated array";
  }
  else {
    echo "Found regular array";
  }
}


my_func(array("foo" => "bar", "hello" => "world"));
# => "Found associated array"

my_func(array(1,2,3,4));
# => "Found regular array"

PHP可以实现这个吗?


1
这个函数会如何处理包含数字和关联索引混合的数组 (array(1, 2, 'foo' => 'bar', 3, 4, 'hello' => 'world'))? - BoltClock
假设数组是同质的,没有混合。 - maček
6个回答

6

只需检查任何键的类型:

function is_associative(array $a) {
    return is_string(key($a));
}

$a = array(1 => 0);
$a2 = array("a" => 0);

var_dump(is_associative($a)); //false
var_dump(is_associative($a2)); //true

我最喜欢这种方法。谢谢 :) - maček

2

如果您的数组很小并且不关心开销(如果它们很大,则这将非常昂贵,因为它需要复制整个数组进行检查,然后处理它),则可以使用 array_values 进行检查:

if ($array === array_values($array)) {}

如果你关心内存,可以这样做:
function isAssociative(array $array) {
    $c = count($array);
    for ($i = 0; $i < $c; $i++) {
        if (!isset($array[$i])) {
            return true;
        }
    }
    return false;
}

请注意,由于需要迭代,这个过程可能会比较慢,但它应该更加内存高效,因为它不需要对数组进行任何复制。
编辑:考虑到您的同质化需求,您可以简单地这样做:
if (isset($array[0])) {
    // Non-Associative
} else {
    // Associative
}

但请注意,数字也可以作为关联数组的有效键。我假设你说的是具有字符串键的关联数组(这是上面的if语句所处理的)...


关于您的编辑。您可以拥有一个没有键“0”的数字数组,例如array(1 => null) - Artefacto
那么它在技术上不是一个数组,而仍然是一个哈希表(因此是一个关联数组)。数组只会有从0到最大值的顺序数字索引... - ircmaxell

2
假设$foo是同质的,只需检查一个键的类型即可。
<?php

function my_func(array $foo) {
    if (!is_int(key($foo))) {
        echo 'Found associative array';
    } else {
        echo 'Found indexed array';
    }
}

?>

0

这是一种方法,通过检查是否存在由非数字值组成的键来实现:

function my_func($arr) {
   $keys = array_keys($arr); // pull out all the keys into a new array
   $non_numeric = preg_grep('/\D/', $keys); // find any keys containing non-digits
   if (count($non_numeric) > 0) {
       return TRUE; // at least one non-numeric key, so it's not a "straight" array
   } else {
       return FALSE: // all keys are numeric, so most likely a straight array
   }
}

0
function is_associative($array) {
  return count(array_keys($array)) != array_filter(array_keys($array), 'is_numeric');
}

0
鉴于您的评论“假设数组是同种类型的;没有混合。”: 只需检查第一个(或最后一个,或随机一个)键是整数还是字符串。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接