views:

61

answers:

6

Without having to change the function signature, I'd like a PHP function to behave differently if given an associated array instead of a regular array.

Note: You can assume arrays are homogenous. E.g., array(1,2,"foo" => "bar") is not accepted and can be ignored.

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"

Is this possible with PHP?

+2  A: 

You COULD use a check with array_values if your arrays are small and you don't care about the overhead (if they are large, this will be quite expensive as it requires copying the entire array just for the check, then disposing of it):

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

If you care about memory, you could do:

function isAssociative(array $array) {
    $c = count($array);
    for ($i = 0; $i < $c; $i++) {
        if (!isset($array[$i])) {
            return true;
        }
    }
    return false;
}

Note that this will be fairly slow, since it involves iteration, but it should be much more memory efficient since it doesn't require any copying of the array.

Edit: Considering your homogenious requirement, you can simply do this:

if (isset($array[0])) {
    // Non-Associative
} else {
    // Associative
}

But note that numerics are valid keys for an associative array. I assume you're talking about an associative array with string keys (which is what the above if will handle)...

ircmaxell
Regarding your edit. You can have a numeric array that doesn't have the key `0`, e.g. `array(1 => null)`
Artefacto
Then it's not technically an array, it's still a hash table (and hence an associative array). Arrays would only have sequential numeric indexes from 0 to max...
ircmaxell
A: 

In the light of your comment Assume arrays are homogenous; no mixtures.: Just check if first (or last, or random) key is an integer or a string.

Mchl
A: 

This would be one way of doing it, by checking if there's any keys consisting of non-numeric values:

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
   }
}
Marc B
+4  A: 

Just check the type of any key:

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
Artefacto
I like this method best. Thanks :)
macek
+2  A: 

Assuming $foo is homogeneous, just check the type of one key and that's it.

<?php

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

?>
BoltClock
A: 
function is_associative($array) {
  return count(array_keys($array)) != array_filter(array_keys($array), 'is_numeric');
}
Yorirou