Take the 2-minute tour ×

I'd like to be able to pass an array to a function and have the function behave differently depending on whether it's a "list" style array or a "hash" style array. E.g.:

myfunc(array("One", "Two", "Three")); // works
myfunc(array(1=>"One", 2=>"Two", 3=>"Three")); also works, but understands it's a hash

Might output something like:

One, Two, Three
1=One, 2=Two, 3=Three

ie: the function does something differently when it "detects" it's being passed a hash rather than an array. Can you tell I'm coming from a Perl background where %hashes are different references from @arrays?

I believe my example is significant because we can't just test to see whether the key is numeric, because you could very well be using numeric keys in your hash.

I'm specifically looking to avoid having to use the messier construct of myfunc(array(array(1=>"One"), array(2=>"Two"), array(3=>"Three")))

share|improve this question
Looking for something like this? stackoverflow.com/questions/173400/… –  watcher May 13 '11 at 19:30
Interesting question. PHP unfortunately does not distinguish array('a','b','c') from array(0=>'a',1=>'b',2=>'c')... –  Tadeck May 13 '11 at 19:31
PHP will always store numeric keys array("1" => "1") as integers. Can't detect that. You can only probe for continually growing keys to differentiate true lists from indexed arrays. –  mario May 13 '11 at 19:35
Correct. Unfortunately it does not distinguish 'simple' arrays and those with numeric strings as keys (see my answer). –  Tadeck May 13 '11 at 19:42
add comment

4 Answers

up vote 6 down vote accepted

Pulled right out of the kohana framework.

public static function is_assoc(array $array)
    // Keys of the array
    $keys = array_keys($array);

    // If the array keys of the keys match the keys, then the array must
    // not be associative (e.g. the keys array looked like {0:0, 1:1...}).
    return array_keys($keys) !== $keys;
share|improve this answer
+1 for elegance –  pedromanoel Jul 3 '13 at 19:43
Very nice indeed. I'm still taking this a little bit on faith.... but it works in my code, so thanks! –  Tom Auger Dec 17 '13 at 16:05
add comment

My solution is to get keys of an array like below and check that if the key is not integer:

private function is_hash($array) {
        return ! is_int($key);
    return false;

It is wrong to get array_keys of a hash array like below:

       "abc" => "gfb",
       "bdc" => "dbc"

will output:

       0 => "abc",
       1 => "bdc"

So, it is not a good idea to compare it with a range of numbers as mentioned in top rated answer. It will always say that it is a hash array if you try to compare keys with a range.

share|improve this answer
Walk me through your function, because there's something I'm missing. You have a foreach loop, but you return on the very first iteration of that loop! What's the point of the loop if you're just returning whether the first key is an integer? Perhaps you meant to set a flag to true and then in our loop if it IS an integer, set the flag to false? –  Tom Auger Dec 20 '11 at 14:24
otherwise you always get an integer value as an array key thats why! –  GO' Dec 27 '11 at 7:42
add comment

PHP treats all arrays as hashes, technically, so there is not an exact way to do this. Your best bet would be the following I believe:

if (array_keys($array) === range(0, count($array) - 1)) {
   //it is a hash
share|improve this answer
This is the only solution that was posted so I'll accept it, despite its inherent limitation of not accounting for non-sequential array indices. This question: stackoverflow.com/questions/173400/… has a lot more solutions, none of which are perfect. –  Tom Auger Jun 15 '11 at 13:27
"non-sequental" can be solved very simply by sorting. –  Explosion Pills Jun 15 '11 at 13:39
add comment

No, PHP does not differentiate arrays where the keys are numeric strings from the arrays where the keys are integers in cases like the following:

$a = array("0"=>'a', "1"=>'b', "2"=>'c');

var_dump(array_keys($a), array_keys($b));

It outputs:

array(3) {
    [0]=> int(0) [1]=> int(1) [2]=> int(2)
array(3) {

(above formatted for readability)

share|improve this answer
add comment

Your Answer


