views:

133

answers:

9

How do I find out if a PHP array was built like this:

array('First', 'Second', 'Third');

Or like this:

array('first' => 'First', 'second' => 'Second', 'third' => 'Third');

???

A: 
print_r($array);
John Conde
I believe "without visually inspecting the array" was more or less implied...
meagar
A: 

There is no difference between

array('First', 'Second', 'Third');

and

array(0 => 'First', 1 => 'Second', 2 => 'Third');

The former just has implicit keys rather than you specifying them

Michael Mrozek
This isn't the code the question uses, where the arrays are indeed different.
meagar
+8  A: 

Try;

function isAssoc($arr)
{
    return array_keys($arr) !== range(0, count($arr) - 1);
}

var_dump(isAssoc(array('a', 'b', 'c'))); // false
var_dump(isAssoc(array("0" => 'a', "1" => 'b', "2" => 'c'))); // false
var_dump(isAssoc(array("1" => 'a', "0" => 'b', "2" => 'c'))); // true
var_dump(isAssoc(array("a" => 'a', "b" => 'b', "c" => 'c'))); // true
Adnan
This will fail on sparse arrays, e.g. `$x[100] = 1;`. How about `count(preg_grep('/\D/', array_keys($arr))) > 0`, which is true if there's any keys with non-digit characters.
Marc B
@Marc A sparse array is arguably more an associative array than a continuously numerically indexed one.
deceze
Perhaps, but nowhere was it specified that the array in question is 0-indexed and keyed contiguously[sp?]. AH well, no biggie. Either method works, but I think mine would be a bit more universal
Marc B
+2  A: 

I have these simple functions in my handy bag o' PHP tools:

function is_flat_array($ar) {
    if (!is_array($ar))
        return false;

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

function is_hash($ar) { 
   if (!is_array($ar))
       return false;

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

I've never tested its performance on large arrays. I mostly use it on arrays with 10 or fewer keys so it's not usually an issue. I suspect it will have better performance than comparing $keys to the generated range 0..count($array).

meagar
A: 
function is_assoc($array) {
    return (is_array($array) 
       && (0 !== count(array_diff_key($array, array_keys(array_keys($array)))) 
       || count($array)==0)); // empty array is also associative
}

here's another

function is_assoc($array) {
    if ( is_array($array) && ! empty($array) ) {
        for ( $i = count($array) - 1; $i; $i-- ) {
            if ( ! array_key_exists($i, $array) ) { return true; }
        }
        return ! array_key_exists(0, $array);
    }
    return false;
}

Gleefully swiped from the is_array comments on the PHP documentation site.

ghoppe
A: 

That's a little tricky, especially that this form array('First', 'Second', 'Third'); implicitly lets PHP generate keys values.

I guess a valid workaround would go something like:

function array_indexed( $array )
{
    $last_k = -1;

    foreach( $array as $k => $v )
    {
        if( $k != $last_k + 1 )
        {
            return false;
        }
        $last_k++;
    }

    return true;
}
msakr
This is going to have extremely poor memory usage for arrays as `foreach` creates a copy of the entire array. Not good, especially when all you're interested in is the array's keys.
meagar
@meagar: Your solution creates several copies inside `array_keys`. Therefore I'd not go blasting a `foreach` solution lightly....
Billy ONeal
@meager: I wasn't aware of that. Thanks for the info.@Billy: I was thinking that but then realized `array_keys` would probably go around using array pointers or something of the sort to traverse the array. Or was I wrong?
msakr
@billy array_keys only copies the array's keys, which are (hopefully) going to be integers or short strings; generally the array's values are where the large chunks of data are going to be
meagar
@meagar: That's highly data dependant. I believe you can elide the copy required for the `foreach` by using reference parameters instead anyway.
Billy ONeal
A: 

programmatically, you can't. I suppose the only way to check in a case like yours would be to do something like: foreach ($myarray as $key => $value) { if ( is_numeric($key) ) { echo "the array appears to use numeric (probably a case of the first)"; } }

but this wouldn't detect the case where the array was built as $array = array(0 => "first", 1 => "second", etc);

pocketfullofcheese
A: 

Hello, If you have php > 5.1 and are only looking for 0-based arrays, you can shrink the code to

$stringKeys = array_diff_key($a, array_values($a));
$isZeroBased = empty($stringKeys);

I Hope this will help you Jerome WAGNER

Jerome WAGNER
A: 
function isAssoc($arr)
{
    return $arr !== array_values($arr);
}
Alix Axel