1

I am new to associative array concept of php. I had never used associative array before this. I came through an example, and got the following code:

function isAssoc($arr)
{
    return array_keys($arr) !== range(0, count($arr) - 1);
}
echo(var_dump(isAssoc(array("0" => 'a', "1" => 'b', "2" => 'c'))).'<br />'); // false
echo(var_dump(isAssoc(array("1" => 'a', "1" => 'b', "2" => 'c'))).'<br />'); //true
echo(var_dump(isAssoc(array("1" => 'a', "0" => 'b', "2" => 'c'))).'<br />'); // true
echo(var_dump(isAssoc(array("a" => 'a', "b" => 'b', "c" => 'c'))).'<br />'); // true

The above function is used to tell whether the array is associate array or not.

I have this doubt why:

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

is not an associative array as it returns false. Whereas,

array("1" => 'a', "0" => 'b', "2" => 'c') //OR
array("1" => 'a', "1" => 'b', "2" => 'c')

is an associative array?

Veer Shrivastav
  • 5,434
  • 11
  • 53
  • 83
  • 3
    I imagine you got this code from here: http://stackoverflow.com/a/173479/129570. As you will see in the comments there, it's widely been pointed out that this code doesn't work correctly. – Oliver Charlesworth Apr 27 '14 at 09:59
  • there is rarely a need to know whether an array is associated or not as regards accessing it. As every array comes with an iterator which always starts at the first record. Therefore 'current($arrayVar)' always returns the first record. Unless it has been explicitly moved. – Ryan Vincent Apr 27 '14 at 10:35
  • @RyanVincent: But if you have an associative array and you know it. You'll access the array elements with key value pair. Else you would treat it as other arrays. – Veer Shrivastav Apr 27 '14 at 10:37
  • 1
    @Veer, i fully appreciate that. Was trying to point out that some people are not aware about the implied iterator and often use index 0 to access the first record. which can cause confusion if it has numeric indexes starting with a different value. – Ryan Vincent Apr 27 '14 at 10:39

3 Answers3

2

The term "associative array" in the PHP manual is used to differentiate from "indexed array". In PHP, all arrays are by definition associative in that they contain key/value pairs (the association). However, the documentation aims to refer to "associative" when it means "non-indexed", for clarity. This is the important point.

So what is an "indexed array"? By "indexed", it is meant that the keys of the array are starting at 0 and incrementing by one. Whether the keys are explicitly set at definition (array(0 => 'a', 1 => 'b')) or implicit (array('a', 'b')) makes no difference. Any other sequence of keys would be referred to as "associative".

Note that how the PHP manual uses the term "associative" doesn't necessarily correlate precisely with the same term's use elsewhere.

salathe
  • 51,324
  • 12
  • 104
  • 132
  • In the PHP manual the terms *associative array* and *numeric array* are often used to distinguish between those, e.g. *"Returns an array of associative or numeric arrays holding result rows."* ([ref](http://www.php.net/manual/en/mysqli-result.fetch-all.php)) – hakre Apr 27 '14 at 11:26
2

All arrays in PHP are associative, you can consider it to be tuple if all keys are numeric (integers but not necessarily of that type), continuous and start from 0.

Simple check would be:

function is_assoc(array $array) 
{
  $keys = array_keys($array);
  $keys_keys = array_keys($keys);

  return $keys_keys !== $keys;
}

It would yield same results as the one you've linked to/used.

A hint here would be excerpt from json_decode documentation:

assoc
When TRUE, returned objects will be converted into associative arrays.

Even if it returns "numeric" and "indexed" array it's still associative.

Another example would be:

$array = ["0" => "a", "1" => "b", "2" => "c"]; # numeric, continuous, starts from 0
json_encode($array); # (array) ["a","b","c"]

While:

$array = ["0" => "a", "2" => "b", "3" => "c"]; # numeric, NOT continuous, starts from 0
json_encode($array); # (list) {"0":"a","2":"b","3":"c"}
Dejan Marjanović
  • 19,244
  • 7
  • 52
  • 66
1

The function you're referring to has flaws and it is not authoritative about the fact whether or not an array in PHP is associative or not.

In-fact, in PHP it is not strictly defined what the term associative array actually means.

However it is important to understand that

  1. PHP is loosely typed
  2. PHP differs in array keys between integer (bool, NULL, float, integer, numeric string represented as integer) and string (nun-numeric strings) for keys.

Most likely an associative array in PHP is one where inside the array (that is after creating it, not while it seems when writing the array definition) that all keys in that array are strings.

But keep in mind that no set-in-stone definition exists. PHP arrays are just a mixture of array and hash-map where you need to know both without having both properly differentiated and the need to keep in mind the difference between numeric and non-numeric keys and how the loosely type-system of PHP converts for the array key needs.

First page to go as usual:


For those who really can only understand it with code, here the pony goes:

function is_array_assoc(array $array) {
    return is_array($array);
}

If you can ensure that you're not using an error-handler that catches catchable errors, then the following code is correct, too:

function is_array_assoc(array $array) {
    return TRUE;
}

The later example makes it perhaps a bit more clear that all arrays in PHP are associative.

hakre
  • 193,403
  • 52
  • 435
  • 836
  • Din't get you can you please provide with some code.? – Veer Shrivastav Apr 27 '14 at 10:29
  • @Veer: There is no code. What an associative array is or is not is not sharpely defined. Therefore there can be no code. Instead, re-read the page in the PHP manual about the array type and learn about it's specialities (that requires re-reading that page next time you're using arrays and so on and so forth. PHP is a language with many special rules, so you can't keep those all in your head. instead refer to the manual). – hakre Apr 27 '14 at 10:32
  • @Veer: Now there is some code. All arrays in PHP are associative if you ask me, each key associates to a value. – hakre Apr 27 '14 at 10:36
  • din't get you. If every array is associative, that is with key value pair, then can you please explain, how can we read an array like this: `["Veer","hakre","user12332412"]` in key value type.? – Veer Shrivastav Apr 27 '14 at 10:40
  • @Veer `var_dump` it and you will see for yourself. – Dejan Marjanović Apr 27 '14 at 10:42
  • 1
    @Veer: You read an array normally by traversing it via `foreach`. You can read each key and each value. More oldskool is the iteration via `each` which still works. – hakre Apr 27 '14 at 10:44
  • @hakre: Even the first function would generate a Catchable fatal error. Not that it matters anyway, as the function is quite pointless and has no practical use :) – Amal Murali Apr 27 '14 at 11:13
  • @AmalMurali: The first function does generate a Catchable fatal error, which would be problematic as this would allow (if caught by an error handler) to pass non-array parameters. Therefore for this case, the `is_array()` function needs to be called despite the parameter-typehint. – hakre Apr 27 '14 at 11:17
  • I don't know how this has not been addressed. My client expects to receive key-value pairs (aka associative arrays), and it just so happens that my keys are just numbers 0 through 13. Any k-v pairs sent to my client that start with 0 (and any consecutive ones) automatically have their keys removed, leaving my client broken as it was expecting to find a key for each value instead of just values. Yikes. – Merricat Mar 19 '22 at 03:20
  • @Merricat: The keys `0` to `13` are not removed, however if they were as strings, then they are as integers. In case it causes an issue, e.g. you want it as a JSON Object, not JSON Array, you can use the `JSON_FORCE_OBJECT` flag: https://3v4l.org/9FHY5 – hakre Mar 21 '22 at 16:02
  • @hakre By removed I meant that they become implicit and therefore are not shown as keys, which changes the data type on the receiving end. Also, I don't want it encoded at that step. Are you suggesting I encode it then decode it just to preserve the indices as strings? like `json_decode(json_encode(range(0, 13), JSON_FORCE_OBJECT))`. Edit: this seems to have worked! Encoding and re-decoding it preserves the keys (I guess by converting them to string?) – Merricat Mar 22 '22 at 18:13
  • @hakre Actually casting it to an stdObject with `object($array)` fixed it for me (instead of encoding and re-decoding). – Merricat Mar 22 '22 at 18:22
  • @Merricat: Yes, when no JSON is involved, an `(object) $array` cast is the better option, didn't know about your concrete use-case. Object property names are always strings IIRC, however there may be some details depending on PHP version if you go far back (_or_ var_dump did not highlight this, perhaps check w/ searialize, anyway:) https://3v4l.org/oX8DJ - yes int before PHP 7.2, also here w/ serialize: https://3v4l.org/TCOPo – hakre Mar 22 '22 at 18:43