Reputation: 218
I am looping through several thousands of rows from a mysql result and adding them to different arrays.
I get a reference to the last element in the array to operate on (for reasons outside the scope of this question).
I.e. (just an example of the scenario)
$myarray = array();
$result = &$myarray;
$row = &$result[count($result)-1]
Of course this works, but as this thread ( Why is calling a function (such as strlen, count etc) on a referenced value so slow? ) explains , calling a function which doesnt expect a variable by reference , With a variable by reference, causes the function to make a copy of the variable to operate on.
As my $result array grows to thousands of elements , continuously calling count on it , causing copies of it being made , makes the code unusable slow.
How can I get around this - Without suggesting to not use variables by reference. Also, I cant keep separate rowcounters.
Basically I need to know how to dereference a by-reference variable (which I understand cant be done) , or some other way to get a array length ? , or a way to get a reference to the last row in an array (without popping it)
Bearing in mind the array could also be empty.
Already took me ages to find out that This is the problem , so I would really appreciate any help with solving the problem.
EDIT To everyone that says that count cannot possibly be slower than end/key: Just run this simple test to confirm
//setup array of 10 000 elements
$ar = array();
for ($i = 0 ; $i < 10000 ; $i++)
{
$ar[] = $i;
}
//get a reference to it
$ref = &$ar;
error_log (date("Y/m/d H:i:s")." : speed test 1 \r\n",3,"debug.log");
//do 10 000 counts on the referenced array
for ($i = 0 ; $i < 10000 ; $i++)
{
$size = count($ref);
}
error_log (date("Y/m/d H:i:s")." : speed test 2 \r\n",3,"debug.log");
//do 10 000 end/key on the referenced array
for ($i = 0 ; $i < 10000 ; $i++)
{
reset($ref);
end($ref);
$size = key($ref);
}
error_log (date("Y/m/d H:i:s")." : end \r\n",3,"debug.log");
Output: 15 seconds to do the counts ... less than a second to do the end/key
2012/07/10 17:25:38 : speed test 1
2012/07/10 17:25:53 : speed test 2
2012/07/10 17:25:53 : end
Upvotes: 4
Views: 216
Reputation: 59699
I'm still not sure I understand why this is necessary. However, you've indexed the array as a numerical sequential array, so you can do this "trick" to get the size:
// Make sure the array pointer is at the end of the array
end($result); // Not sure if this is necessary based on your description
$size = key($result) + 1; // Get the numeric key of the last array element
Note that both end()
and key()
take their parameters by reference. However, I wouldn't be surprised if they're now operating on references of references, but this is something you can investigate.
Upvotes: 3
Reputation: 12420
You should have a look to the SPL data structures. Maybe a simple SplHeap or SplDoublyLinkedList can fit to your requirements. Moreover, performances are pretty good!
Upvotes: 0
Reputation: 2603
depending on your other needs, that you mentioned but didn't descripe, maybe a few of the realy oldschool (deep level) functions coud help:
end($result); // set pointer to (current) last element
$pos = key($result); //index of the last element
$row = &$result($pos);
edit: I type too slow :)
Upvotes: 1