PHP array memory consumption for unused offsets - php

sorry if this question has already been answered somewhere else, but I couldn't find it (possibly because I had a tough time phrasing my question properly).
I'm working with a double dimension array which is the result set from a db query. Ive got the array set up so the array's first index is the pk of the row array so the array would look like...
$array[345] = {'id' => 345,
'info1' => 'lorem',
'infor2' => 'ipsum'}
$array[448] = {'id' => 448,
'info1' => 'lorem',
'infor2' => 'ipsum'}
My question... I know the index's are being passed as integers. So, I'm thinking (perhaps incorrectly) that they are being treated as numerical offsets by the array (as opposed to associatively.) So, if the first index is 345, does the system automatically reserve space in memory for index's 0 through 344? The code all works perfectly, but I am wondering if this method is going to eat up a boatload of memory. Especially if I get to the point where there are only two arrays being stored at 322,343 and 554,324. Sorry if it's a dumb question, thanks for any answers.

No, arrays are hashmaps and keys dont equal offsets, e.g
$foo = array(0 => 'x', 1000 => 'y')
is two elements only. There is nothing reserved inbetween.

Related

PHP ksort unexpected behavior [duplicate]

This question already has answers here:
ksort produces wrong result when dealing with alphanumeric characters
(6 answers)
Closed 4 years ago.
Let me tell you from the start: I know about the sort flags of this function. When I use SORT_STRING it works well, but the default flag SORT_REGULAR works weird, or doesn't work at all.
Consider an array like below.
$arr = [
'27a' => 'foo',
'27b' => 'foo',
'27c' => 'foo',
'27' => 'foo',
];
When I try to sort using ksort, it gives an array without being sorted in any obvious logic.
ksort($arr);
print_r($arr);
// this prints
Array
(
[27a] => foo
[27] => foo
[27b] => foo
[27c] => foo
)
As one could say the keys are neither numerically nor alphanumerically nor naturally sorted. Even more strangely, when I change the order of the source array, it gives a different result:
$arr = [
'27a' => 'foo',
'27' => 'foo',
'27b' => 'foo',
'27c' => 'foo',
];
ksort($arr);
print_r($arr);
// this prints
Array
(
[27b] => foo
[27c] => foo
[27] => foo
[27a] => foo
)
Does anyone know the logic behind this? Is this a bug or am I missing something?
EDIT: Thank you all for being interested in and answering my question. Although it's marked as duplicate, the other question didn't mention the weirder part: Why changing the order of the source array changes the result? It should give the same result with the same input set. Shall we discuss this too?
The reason that is happening is because it sees keys like '27a' as a string, and keys like '27' as an integer, even though it is quoted. You'll see the same results if you remove the quotes from the 27 key.
And, as the ksort page says: "Warning: Be careful when sorting arrays with mixed types values because sort() can produce unpredictable results."
Weird behavior for sure- unfortunately the best way to produce expected results when you have keys that look like integers (even if they are strings), is to specify the sort flag like SORT_STRING to ensure that you get the expected results every time.

Best / Most Efficient averages of multi-dimensional array PHP

I am working on a application that has the following the following:
Each month, an API returns a series of values depending on the data, so something like (These are updated everyday so the results are cached)
$data = array(
array("2016-02-03" => 3", "2016-02-04" => 4", "2016-02-05" => 1"),
array("2016-02-03" => 1", "2016-02-04" => 2", "2016-02-05" => 3"),
array("2016-02-03" => 60", "2016-02-04" => 18", "2016-02-05" => 3"),
);
What I am therefore trying to achieve is that the algorithm will take the first key ("2016-02-03") then iterate through all of the sub arrays and find the values for this key and then sums them up and calculates the average, finally add this to another array. This will continue until there are no more keys left.
The problem is, I could have a huge foreach loop and do it that way, but the problem is, there are over 40 values and all contain around 30 days worth of data so this would be inefficient.
Is there an alternative to solving this problem? One that won't be intensive and slow?
I can only imagine the sulotion is to run the server for as long as it takes. I also suggest that after each date match you add the value to your new array and unset the index to reduce memory and the time needed to loop through everything.
In your new array you can have the syntax:
[ "Year-month-day" => [...] ]
Where the dots will be all the values.

PHP comparing two (potentially differently-sized) 2D arrays

I'm trying to compare two 2D arrays in PHP and my head is hurting with all the recursion - this'll probably be obvious to someone who's used to it.
I have two 2D arrays which look like this, called $submittedArray2D and $dbArray:
{
[0] => {
[0] => 'name'
[1] => 'sectors'
[2] => 'address'
[3] => 'url'
}
[1] => {
[0] => 'name'
[1] => 'sectors'
[2] => 'address'
[3] => 'url'
}
...
}
$submittedArray2D comes from user input, while $dbArray holds what is already in the database.
I want to compare them to see if any of the values have been updated in $submittedArray2D, and save those changes to $dbArray accordingly.
I also want to pass any changed addresses to a separate function for geocoding, the results of which will be stored in another database field, where the keys reference the same entry in $dbArray (so $geocode[4] refers to $dbArray[4], for example).
I've tried out some foreach statements to go through the arrays sequentially, but this breaks down if one of the entries has been removed from the middle of the array, because the two arrays are no longer in sequence. I'm wondering whether some kind of ID for each array entry might make sense, but I'm not sure where to start.
Any ideas or pointers would be much appreciated!
I managed it in the end by storing a unique ID alongside each array element, that was it was possible to loop through and check whether that ID existed in the comparator array and then check whether the address had changed, and if so store the change (along with the ID) in a separate array for processing.

Better data structure or algorithm than iterative searching on multidimensional arrays to find corresponding values?

For a site I am working on I use a library to get a list of states. It returns a numerically indexed array of states, each with three keys: stateCode, stateName, and stateSeg. It looks like this:
array
0 => &
array
'stateCode' => string 'AL' (length=2)
'stateName' => string 'Alabama' (length=7)
'stateSeg' => string 'alabama-al' (length=10)
1 => &
array
'stateCode' => string 'AK' (length=2)
'stateName' => string 'Alaska' (length=6)
'stateSeg' => string 'alaska-ak' (length=9)
2 => &
array
'stateCode' => string 'AZ' (length=2)
'stateName' => string 'Arizona' (length=7)
'stateSeg' => string 'arizona-az' (length=10)
I often find myself with one of the three values and needing to look up its corresponding value. To do this I find myself constantly having to iterate through the array of states to find the data I need. Like this:
foreach ($this->data['stateList'] as $state)
{
if ($state['stateCode'] == $searchParams['state'])
{
$stateSeg = $state['stateSeg'];
break;
}
}
$url = BASEURL . '/' . $stateSeg . ".html";
This seems inefficient to me. I think the most efficient solution I’ve been able to come up with is to turn states into objects and put them in array with multiple keys for stateCode, stateSeg, and stateName each pointing to the same state object, so they can be referenced like this:
stateList[‘CA’]->getStateSeg();
or
stateList[‘Arizona’]->getStateCode();
or
stateList[‘alaska-ak’]->getStateName();
etc…
This also seems like kind of a hack which would result in a rather large array (150 keys pointing to 50 objects) with replicated data (keys replicating data stored within objects).
Anyway, just thought I’d see if there is some kind of pattern for this type of problem. This array of states isn't the only thing I’ve come across where I’ve had to do this sort of iterative searching on multidimensional arrays to find corresponding values.
Question is tagged PHP and the code above is in PHP, but I am interested in elegant solutions in any language.
If php supports references and I know the state, I'd just pass a reference to the appropriate array element and extract from it the necessary field.
Alternatively, if you never know in advance what state you can get, create and use a map (associative container/array), let its efficient implementation take care of quickly finding whatever you need. Seems like you may need several of them.
Also, I wonder if you could get rid of everything except the "alaska-ak" strings. The data appears highly redundant.
I think your basic idea with the object and the arrays is not that bad, but instead of creating actually objects, I would just refer to the existing objects (better: array data). Let's see your original list again:
array
0 => &
array
'stateCode' => string 'AL' (length=2)
'stateName' => string 'Alabama' (length=7)
'stateSeg' => string 'alabama-al' (length=10)
1 => &
array
'stateCode' => string 'AK' (length=2)
'stateName' => string 'Alaska' (length=6)
'stateSeg' => string 'alaska-ak' (length=9)
2 => &
...
Each state object has an identifier, the array key: 0, 1, 2, ... .
All you need to do is to create three indexes based on key. You use the value as key (e.g. "AL" for "stateCode" index) and as value you take the array index, 0:
$indexStateCode['AL'] = 0;
You can then already look this up quickly:
$states[$indexStateCode['AL']];
Encapsulate this into a class with ArrayAccess and then on request instantiate the state object. You don't need it earlier.
Could you store the states in a mysql/sqlite table and use the database engine to do the lookup?
This seems inefficient to me
It isn't. Even worse-case, iterating through 50 items is probably an order of magnitude faster than querying a db.
a library to get a list of states
Not sure why you'd need a library to do this. But I'd either change the library to return the array how you need it, or wrap it in another module.
The data is somewhat redundant... All you need is two items: the state code and the state name. You can construct the "state seg" from those two. So keep a state code map and a state name map.

PHP Array Efficiency and Memory Clarification

When declaring an Array in PHP, the index's may be created out of order...I.e
Array[1] = 1
Array[19] = 2
Array[4] = 3
My question. In creating an array like this, is the length 19 with nulls in between? If I attempted to get Array[3] would it come as undefined or throw an error? Also, how does this affect memory. Would the memory of 3 index's be taken up or 19?
Also currently a developer wrote a script with 3 arrays FailedUpdates[] FailedDeletes[] FailedInserts[]
Is it more efficient to do it this way, or do it in the case of an associative array controlling several sub arrays
"Failures" array(){
["Updates"] => array(){
[0] => 12
[1] => 41
}
["Deletes"] => array(){
[0] => 122
[1] => 414
[1] => 43
}
["Inserts"] => array(){
[0] => 12
}
}
Memory effiency isn't really something you need to worry about in PHP unless you're dealing with really huge arrays / huge numbers of variables.
An array in PHP isn't really like an array in C++ or a similar lower-level language; an array in PHP is a map. You have a list of keys (which must be unique and all of type string or integer), and a list of values corresponding to the keys. So the following is a legal array:
array(0 => 'butt', 1 => 'potato', 2 => 'tulip')
but so is
array(5 => 'i', 'barry' => 6, 19 => array(-1 => array(), 7 => 'smock'))
In both cases there are 3 entries in the array, hence 3 keys and 3 values.
In addition to the keys and values in the array, one array may be distinguished from another by the order in which the key/value pairs occur. If you define an array so that it has nonnegative integers as keys, this will often be the expected order. The order matters when you use constructs like foreach().
array[3] will be undefined/unset but not causing an error, and the array will use only memory for that 3 values - php isn't like C where you have to look at those things.
Accessing $arr[3] gives a notice: Notice: Undefined offset: 3 in /data/home/sjoerd/public_html/svnreps/test/a.php on line 3. You can avoid this by checking with isset() or array_key_exists().
There are no nulls stored.
Having empty elements won't take up extra memory.
Whether you should use multiple variables or an array depends on the context and how you use the variables.

Categories