Are numeric and associative arrays in PHP two different things? - php

This is a deeper dive into a previous question I had here: Can items in PHP associative arrays not be accessed numerically (i.e. by index)?
According to W3Schools, :
In PHP, there are three kind of
arrays:
Numeric array - An array with a numeric index
Associative array - An array where each ID key is associated with a value
Multidimensional array - An array containing one or more arrays
But is this accurate? Each element in the array can be assigned either an index or a string as a key- so what happens when the two are mixed in the same array?
$myArray[0] = 'value1';
$myArray['one'] = 'value2';

All arrays in PHP are the same; they're implemented as hash maps which associate keys to values, whatever type the keys may be.
Manual:
The indexed and associative array types are the same type in PHP, which can both contain integer and string indices.
If an array had both numeric and non-numeric indices, though, I'd still call it an associative array. The meaning of "associative" still stands.
Wikipedia:
An associative array is an abstract data type composed of a collection of unique keys and a collection of values, where each key is associated with one value (or set of values).
...
From the perspective of a computer programmer, an associative array can be viewed as a generalization of an array. While a regular array maps an integer key (index) to a value of arbitrary data type, an associative array's keys can also be arbitrarily typed. In some programming languages, such as Python, the keys of an associative array do not even need to be of the same type.
For the last sentence, the same applies for PHP, as shown in your example.

PHP doesn't really have arrays. They are dictionaries. Numeric keys are allowed at the same time as string keys. They can be mixed and do coexist.
(Actually string keys like "123" are always treated as integers. PHP does not keep the type information for them.)
If you want a different behaviour you could implement and extend ArrayObject however. And it would be possible to implement a map, where numeric keys functioned as alias to string indexes.

In general, you should read the official documentation rather than W3Schools.
An array can contain whatever members it wants with whatever keys it wants.
The description provided by W3Schools is quite ambiguous, or even wrong.
Numeric array - An array with a numeric index
I'd say a numeric array is an array with only integer indexes. An array with one I'd probably call a mixed (or associative, see below) array, if I had to call it anything.
Associative array - An array where each ID key is associated with a value.
I don't know about that description. I'd say an array can be associative if it maps strings to values instead of numerical indexes.
Multidimensional array - An array containing one or more arraysNumeric array - An array with a numeric index
An associative array can contain arrays too, which makes it multidimensional.
Keep in mind that an array with all numeric keys (even if in a string) will always be treated as a numeric array. This can mean different things in different contexts.
$arr = array(
'1' => 'abc',
2 => 'def'
);
var_dump($arr);
Output
array(2) {
[1]=>
string(3) "abc"
[2]=>
string(3) "def"
}

You get an associative array. Try this code:
$myArray[0] = 'value1';
$myArray['one'] = 'value2';
echo($myArray[1]);
See? It doesn't echo anything.

Something inportant to note about a PHP well ordered numerical array versus a un-ordered numerical PHP array where the order is not respected (3, 1, 2, 0 instead of 0, 1, 2, 3 ...) is when you are working with an API returning JSON payloads. On the client side, e.g a client written in Javascript, and if you're expecting an array and not an object you could have some difficulties. That's why sometime, on the PHP side, you can see something as follows being returned :
return array_values($array);

Related

How does mysql_fetch_array($result_type=MYSQL_BOTH) return both associative and numeric indices?

In the documentation http://php.net/manual/en/function.mysql-fetch-array.php, it states that "By using MYSQL_BOTH (default), you'll get an array with both associative and number indices." But it is my understanding that php arrays can either be associative or numeric, not both. You could obviously create an associative array that contains the numeric indices as well, as keys, but that would double the array count. So how do they do this? Have they made a special exception for this one function? Is what it returns not actually a conventional array but their own special array just for this purpose? Or is there something that I am missing?
According to the PHP Documentation on Arrays a PHP array is "Actually an ordered map", and can be both associative and numeric. Using MYSQL_BOTH uses associative and numeric keys in the same array.

PHP: What is the real meaning of an index in an indexed array?

Say, we make an array like this:
$arr = Array
(
2 => 'c',
1 => 'b',
0 => 'a'
);
When you pass it to array_pop():
array_pop($arr);
And the "last" element would be poped off, which has the index of zero!!
print_r($arr);
Result:
Array
(
[2] => c
[1] => b
)
So, what's the purpose of index?
Isn't it just a different way of saying "numeric keys of associative arrays"?
Is it only PHP dose so, or all the languages treat arrays like this?
Not all languages do this, but PHP does, because PHP is a little weird. It implements arrays more or less like dictionaries. PHP does offer some functions like ksort though, which let you sort the array by key.
And that's what this is: a key. An array has indexes as well, so what you got, is an array where item 2 has key 0. And that's where the confusion starts continues.
PHP: a fractal of bad design has a whole chapter about arrays. Interesting reading material. :)
The reason for this behavior is because arrays in PHP are actually unordered maps.
Because of this, don't think of accessing the arrays in terms of indexes, think of it in terms of keys. Keys can be numbers and they can be strings, but the result is the same; you're still using a map, not a true "array".
Once you accept that fact, you'll understand why PHP includes functions like ksort() for sorting an array by keys and why array_pop() doesn't always remove the highest key value.
It's a PHP thing. Other languages usually provide other structures to provide what is the default behaviour for arrays on PHP. JavaScript for instance will always sort the array:
a = [];
> []
a[1] = 'a';
> "a"
a[2] = 'b';
> "b"
a[0] = 'c';
> "c"
a
> ["c", "a", "b"]
In Java you would need to use a Hash Map or something else to do Associative Arrays. PHP handles data structures more loosely than other languages.
The index allows you to identify and access the elements of the array.
the reason is simple HashTables.
in php internal functions often use HashTables. basically an array is some data in memory and like in C - an array index can only hold integer values but not in php.
php solves this with hashtables. if you asign a index example foo this value is not directly assigned as foo it gets hashed and maybe end internal as 000000000111 and other hash functions.
so php doesn't work directly with your assigned value and this is the reason why you can set an array index like 0 as last index element. internal php work with hashtables that have a "list" with values which index value is assigned to which position in the array.

Can PHP arrays hold items of different type?

In other programming languages the definition of arrays is something which can hold similar kind of elements. For example if I declare something like int i[] it will store integers, but in PHP a single array seems to be holding strings and numbers together.
Will the number/integer be treated as string in such type of array in PHP?
According to the PHP manual you can indeed store heterogeneous types inside a PHP "array" - scroll down to example 3.
Note that even though the example is about keys being ints or strings, the values assigned in the example are also both ints and strings, demonstrating that it is possible to store heterogeneous types.
Be aware that in the case of different-typed keys there is automatic casting involved so you may have surprising results in the case where e.g. a string contains a valid decimal representation.
Yes. A PHP array can have multiple data types in it.
Also, you should note that arrays in PHP actually are represented in the form of key-value pairs, where the elements you will input into the array are values.
You can explicitly define keys too, when entering elements into the array, but when you don't, PHP will use indices starting from 0.
Example:
<?php
$array = array(
"foo" => "bar",
"bar" => "foo",
100 => -100,
-100 => 100,
);
var_dump($array);
?>
PHP will interpret as
array(4) {
["foo"]=>
string(3) "bar"
["bar"]=>
string(3) "foo"
[100]=>
int(-100)
[-100]=>
int(100)
}
Reference- http://php.net/manual/en/language.types.array.php
You can store anything you want in an array.
Will the number/integer be treated as string in such type of array in PHP?
Not upon storing it. However, when you use a value as such, PHP will convert it. The usage of a value determines its interpretation. (Attention, the key is converted upon storing, however, if it is considered numerical)
Not going to put oil on the fire of the PHP Arrays are no arrays here…
But yes, you can put different variable types (string, int, …) together in a PHP thing called Array.

JSON_ENCODE of multidimensional array giving different results

When doing a json_encode a multidimensional array in PHP, I'm noticing a different output simply by naming one of the arrays, as opposed to not naming them. For Example:
$arrytest = array(array('a'=>1, 'b'=>2),array('c'=>3),array('d'=>4));
json_encode($arrytest)
gives a single array of multiple json objects
[{"a":1,"b":2},{"c":3},{"d":4}];
whereas simply assigning a name to the middle array
$arrytest = array(array('a'=>1, 'b'=>2),"secondarray"=>array('c'=>3),array('d'=>4));
json_encode($arrytest)
creates a single json object with multiple json objects inside
{"0":{"a":1,"b":2},"secondarray":{"c":3},"1":{"d":4}};
why would the 1st option not return the same reasults as the 2nd execpt with "1" in place of "secondarray"
In JSON, arrays [] only every have numeric keys, whereas objects {} have string properties. The inclusion of a array key in your second example forces the entire outer structure to be an object by necessity. The inner objects of both examples are made as objects because of the inclusion of string keys a,b,c,d.
If you were to use the JSON_FORCE_OBJECT option on the first example, you should get back a similar structure to the second, with the outer structure an object rather than an array. Without specifying that you want it as an object, the absence of string keys in the outer array causes PHP to assume it is to be encoded as the equivalent array structure in JSON.
$arrytest = array(array('a'=>1, 'b'=>2),array('c'=>3),array('d'=>4));
// Force the outer structure into an object rather than array
echo json_encode($arrytest , JSON_FORCE_OBJECT);
// {"0":{"a":1,"b":2},"1":{"c":3},"2":{"d":4}}
Arrays with continuous numerical keys are encoded as JSON arrays. That's just how it is. Why? Because it makes sense.
Since the keys can be expressed implicitly through the array encoding, there is no reason to explicitly encoded them as object keys.
See all the examples in the json_encode documentation.
At the first option you only have numeric indexes (0, 1 and 2). Although they are not explicitly declared, php automatically creates them.
At the second option, you declare one of the indexes as an string and this makes PHP internally transform all indexes to string.
When you json encode the first array, it's not necessary to show the integers in the generated json string because any decoder should be able to "guess" that they are 0, 1 and 2.
But in the second array, this is necessary, as the decoder must know the key value in your array.
It's pretty simple. No indexes declared in array? Them they are 0, 1, 2, 3 and so on.
output of this as in json form is year1{a,b},year2{c}, year3{d}
**a has value 1 ,b=2,c=3,d=4 stored in array of year1's a,b years2's c and years3's d respectivily
$array1 = array('a'=>1, 'b'=>2);
$array2 = array('c'=>3);
$array3 = array('d'=>4)
$form = array("year1" =>$array1,
"year2" =>$array2,
"year3" =>$array3,
);
$data = json_encode($form);

Using numbers as assoc array keys

It seems to work, but it feels wrong, I assume it is.
Is it wrong?
If so, I currently have an array with keys being mysql database id's and the values being their values.
Would it be better to have the key being "record_"+$id and then explode()ing the key and getting the id from that?
Or is it ok to set your own array keys, and php will just assume they are assoc array keys, rather than indexes?
Thanks
Some built-in PHP functions (like array_merge / array_multisort) will re-index your array:
array_merge() If the input arrays have the same string keys, then the later value for that key will overwrite the previous one. If,
however, the arrays contain numeric keys, the later value will not
overwrite the original value, but will be appended. Values in the
input array with numeric keys will be renumbered with incrementing
keys starting from zero in the result array.
array_multisort() can be used to sort several arrays at once, or a multi-dimensional array by one or more dimensions. Associative
(string) keys will be maintained, but numeric keys will be re-indexed.
I would advise you not to do that, use a proper value instead, or at the very least prefix it with a short _:
foreach ($array as $key => $value)
{
$id = ltrim($key, '_');
// do stuff with the actual $id
}

Categories