The PHP array type is actually more akin to an an ordered map than a traditional C array. It's PHP's original general use data structure. The manual goes as far to say The indexed and associative array types are the same type in PHP, which can both contain integer and string indices.
However, there's a lot of cases where built-in language features will make a distinction between "indexed" arrays (arrays with sequential, integer keys) and "associative" arrays (arrays with non-sequential and/or keys of mixed types).
One example of this is the array_merge function.
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.
If only one array is given and the array is numerically indexed, the keys get reindexed in a continuous way.
What are the other places in PHP where a distinction is made between indexed and associative arrays? I'm specifically interested in the Userland differences, although any insight into the Array implementation in PHP's source would be interesting as well.
Actually, any array, no matter if it's indexed or associative, is a hashtable (plus a doubly-linked list for maintaining the order of elements) in PHP. However, in userland PHP code, indexed and associative arrays almost always serve different purposes and sometimes need to be treated in different ways, so several functions like sort/asort make a distinction between them just for convenience.
The most prevalent one that comes to mind is that an indexed array can be looped over using a traditional for loop, whereas an associative one cannot (because it does not have the numeric indexes):
for ($i = 0; $i < count($indexed_array); $i++)
{
// do something with $indexed_array[$i]
}
Of course, php also has a foreach keyword, which works the same on both types.
.. and then there is SplFixedArray, starting from 5.3, it supports only integer indexes, has fixed size and is generally faster than the native arrays.
One interesting difference I've found is when using json_encode.
json_encode(array(0=>0,1=>1,2=>2));
> [0,1,2]
json_encode(array(0=>0,2=>2));
> {"0":0,"2":2}
As a lone example this makes sense, but it's more surprising when combined with, say, array_filter.
$f = function($x) { return $x != 1; };
json_encode(array_filter(array(0,1,2), $f));
> {"0":0,"2":2}
We started off with a numeric array, filtered some elements out, but the resulting json is an associative array!
Note that we can get the desired json by using array_values.
json_encode(array_values(array_filter(array(0,1,2),$f)));
> [0,2]
Pretty much all of the core sorting functions (with all the sort, ksort, asort variations depending on whether you want to maintain key association and so on).
Related
Associative array elements are implicitly ordered.
As far as I know regarding their analogue in JS (objects) there are no guarantees about the element order.
array_slice is a function dependent on the elements order.
Is it safe to assume that the result of array_slice will be consistent with the order an associative array will be iterated in using a foreach statement ?
PHP's arrays and Javascript's objects are not comparable.
PHP's arrays are ordered, associative data structures. Javascript doesn't have any equivalent to that.* PHP's arrays aren't implicitly ordered, they're explicitly ordered. That applies to both numeric and string keys.
Yes, array_slice is safe to use on them. Note that it has an explicit $preserve_keys parameter which you must set to true if you want to keep your arrays associative; otherwise they will be re-indexed numerically.
* Javascript only has fundamentally unordered, associative objects. Recent ECMAScript versions specify some ordering for them, but it's not really controllable by the user. Javascript's Array adds a usage pattern on top of those unordered objects which lets you have ordered, but non-associative data structures.
I have an array of rows from MySQL query. What I need to do is sort them by one of the fields (unsigned int type). I looked through reference, but did not understand how exactly do I sort arrays of objects, because PHP does not seem to have something like operator overloading (what you do in C++), and some existing functions say they're unstable, meaning that with 2 equal elements their position in sorted array is undefined, which sounds really weird IMO.
So, what's the general approach in PHP when you need to sort an array of objects?
You'll need to write your own function to do the comparison. Once you have that function, you can then use usort - http://php.net/manual/en/function.usort.php
Note that this also works with sorting an array of objects, you just have to change your comparison function.
If I have an array which is using numerical keys and I add a key far outside the range so far, does it create the intermediate keys as well. For example if I have
$array = array(1,2,3,4);
$array[9] = 10;
Will this cause php to internally reserve memory for the keys 4-8 even though they don't have a value with them.
The reason I ask is I have a large 2D array which I want to use for memoization in a dynamic programming algorithm because only a small number of the total cells will need to be computed. However it would be taxing on the memory to have an empty array of that size for the full 2D array. Is there a better way to do 2 key memoization? I could use an associative array and append the keys with a separator or some scheme like that but if php won't make the extra keys I would rather (for simplicity and readability) just use the 2D array. Thoughts?
This may not fully answer your question, but should help in finding an answer, at least to the first question.
Create this program.
$arr = array(1, 2, 3, 4);
sleep(10);
$arr[100000] = 1;
sleep(10);
Now run it and monitor its memory usage.
In the first ten seconds, the program reserves memory for a small array.
In the next ten seconds, if the array reserves space for the unused indices, the memory usage goes ridiculously high compared to the previous one. If it doesn't, though, the memory used will only grow slightly.
This should give you an idea of the effect of your final program, whether or not using a 2D array is a good idea.
Don't worry, it won't make any extra keys. PHP is not like that, even arrays that you think are regular are associative arrays. You can even combine PHP arrays like this:
array(
1 => 121,
2 => 2112,
'stuff' => array('morestuff'),
'foo' => 1231
)
With PHP its very comfortable which can be good and bad also.
It doesn't seem like it will allocate a placeholder or use any memory for the unused keys, based on Doug T.'s response. Hope this helps!
I typically code in Python, Java, or C. I'm taking on a project in PHP and I'm reading up on arrays in PHP and I'm utterly baffled. If I am understanding correctly, the numerical indices in PHP don't necessarily correspond to position and are just keys like in a dict in Python. So, when you shuffle a PHP array, the order of the elements will change, but their keys will remain the same. So when calling array[9], you might actually be getting the first element of the array if the shuffle ordered the elements that way. This raises a bunch of questions:
Is a PHP array, then, always just some kind of ordered hash table?
And what does that mean for overhead? In Python, lists function like
a classic array data structure and dictionaries more along the lines
of a hash structure. PHP seems to combine the two by assigning unique
keys to every value AND keeping track of the order of those values. If I want to use an associative array structure for constant time lookup, am I in a far worse off position than I would be with a Python dictionary because of this ordering overhead? Are there PHP data structures that are ONLY arrays or ONLY hash tables?
What happens when you remove a value from a numbered PHP array? If I
have an array, [1, 2, 3, 4, 5], I remove 4 from the array, and then
try to access array[3], is it going to give me an error, since I
removed the element with the key 3? Or does PHP do some kind of key
adjusting in such a case?
If you change the ordering of an array (i.e., through a sort or a
shuffle), is the only way to have the indices correspond to the
position to copy the array to a new array using array_values().
http://php.net/manual/en/class.splfixedarray.php
This code:
$arr = array(0,1,2,3,4);
unset($arr[3]);
echo $arr[3]; // undefined index warning, execution continues;
echo isset($arr[3]) ? $arr[3] : '';
print_r($arr);
The print_r() outputs:
Array
(
[0] => 0
[1] => 1
[2] => 2
[4] => 4
)
This depends on the function you choose. Some maintain index association, some do not.
Protip:
Never expect two seemingly-similar PHP functions to behave anything like each other. It's the "English" of programming languages: full of crap stolen from other languages and loads of conventions that contradict each other, but everyone speaks it so hop on board the freedom train.
'murca.
I iterate over an array of arrays and access the array's value through associative keys, this is a code snippet. Note: i never iterate over the total array but only with a window of 10.
//extract array from a db table (not real code)
$array = $query->executeAndFetchAssociative;
$window_start = 0;
for($i = $window_start; $i<count($array) && $i<$window_start+10; $i++)
echo($entry["db_field"]);
This is a sort of paginator for a web interface. I receive the windows_start value and display hte next 10 values.
A conceptual execution:
Receive the windows_start number
Start the cycle entering the window_start-TH array of the outer array
Display the value of a field of the inner array via associative index
Move to window_start+1
The inner arrays have about 40 fields. The outer array can grow a lot as it rapresent a database table.
Now i see that as the outer array gets bigger the execution over the windows of 10 takes more and more time.
I need some "performance theory" on my code:
If I enter the values of inner arrays via numeric key can I have better performance? In general is quickier accessing the array values with numeric index than accessing with associative index (a string)?
How does it cost entering a random entry ($array[random_num]) of an array of length N ? O(N), O(N/2) just for example
Finally the speed of iterating over an array depends on the array lenght? I mean i always iterate on 10 elements of the array, but how does the array lenght impact on my fixed length iteration?
Thanks
Alberto
If I enter the values of inner arrays via numeric key can I have
better performance? In general is quicker accessing the array values
with numeric index than accessing with associative index (a string)?
There might be a theoretical speed difference for integer-based vs string-based access (it depends on what the hash function for integer values does vs the one for string values, I have not read the PHP source to get a definite answer), but it's certainly going to be negligible.
How does it cost entering a random entry ($array[random_num]) of an
array of length N ? O(N), O(N/2) just for example
Arrays in PHP are implemented through hash tables, which means that insertion is amortized O(1) -- almost all insertions are O(1), but a few may be O(n). By the way, O(n) and O(n/2) are the same thing; you might want to revisit a text on algorithmic complexity.
Finally the speed of iterating over an array depends on the array
length? I mean i always iterate on 10 elements of the array, but how
does the array length impact on my fixed length iteration?
No, array length is not a factor.
The performance drops not because of how you access your array but because of the fact that you seem to be loading all of the records from your database just to process 10 of them.
You should move the paging logic to the database itself by including an offset and a limit in your SQL query.
Premature optimization is the root of all evil. Additional numeric and associative arrays have a very different semantic meaning and are therefore usually not interchangeable. And last but not least: No. Arrays in PHP are implemented as Hashmaps and accessing them by key is always O(1)
In your case (pagination) it's much more usefull to only fetch the items you want to display instead of fetching all and slicing them later. SQL has the LIMIT 10 OFFSET 20-syntax for that.