2
\$\begingroup\$

I have a script which get data from MongoDB in the form of array and show the result. The array has a number of records in the thousands. A sample array is as follows:

array(2) {   ["mac"]=> string(17) "2c:33:7a:10:f8:39" int(1478199995) ["duration"]=> int(5) }

array(2) {   ["mac"]=> string(17) "38:0b:40:ad:03:53" int(1478203338) ["duration"]=> int(3) }

array(2) {   ["mac"]=> string(17) "38:0b:40:ad:03:53" int(1478201111) ["duration"]=> int(7) }

array(2) {   ["mac"]=> string(17) "2c:33:7a:10:f8:39" int(1478206709) ["duration"]=> int(7) }

array(2) {   ["mac"]=> string(17) "38:0b:40:ad:03:53" int(1478202821) ["duration"]=> int(6) }

array(2) {   ["mac"]=> string(17) "2c:33:7a:10:f8:39" int(1478202366) ["duration"]=> int(4) }

array(2) {   ["mac"]=> string(17) "38:0b:40:ad:03:53" int(1478205023) ["duration"]=> int(2) } 

I am showing record with respect mac address like in above array MAC address "2c:33:7a:10:f8:39" has three records and "38:0b:40:ad:03:53" has four, so I will add duration of each record and show on browser like this

2c:33:7a:10:f8:39          16sec
38:0b:40:ad:03:53          18sec

I am doing this by following logic which I think is too slow for 5000 to 6000 records.

I first get the MAC address in an array and remove duplication and then run a for loop on that array and add all duration for specific MAC my code is as below.

<?php
 foreach ($cursor as $document) {
 array_push($arr,$document["mac"]);
 }
 $arr=array_unique($arr);
 $duration=0;

 for($i=0;$i<count($arr);$i++){

foreach ($cursor as $document) {

if($document["mac"]==$arr[$i])
{

$duration+=$document['assoc_time'];

}

echo $arr[$i]."      ".$duration;
}

?>

How I can make this process fast and how to perform this task in only one foreach loop.

\$\endgroup\$
0

3 Answers 3

1
\$\begingroup\$

You can do this in only one foreach, making it faster and intelligible for future modification or reuse. The approach I propose is as follows:

//(some sort of pythonish pseudocode)
// let cursor be the array with the mac addresses and duration
result = [] // empty array
for each element in cursor as document:
  document['mac'] is not a key of result then:
    result[ document['mac'] ] = document['duration']
  otherwise
    result[ document['mac'] ] += document['duration']

This way you can quickly check your data, it is very handy. The only difference is that you'll get an array like this:

[
   'mac1' => 'total duration in integer type',
   'mac2' => 'total duration in integer type for mac2'
   ... etc ..
]

In case you really need the current result array structure, you can do this after the first loop:

//(some sort of pseudocode)
arr = [] //initialize the array
for each element in result as mac => duration:
  arr[] = [ 'mac' => mac, 'assoc_time' => duration ]

The difference between nesting two (possibly) big loops and just checking if a key exists in an array is significant. Now let's write a few lines of PHP code:

<?php
$result = array(); // maybe just $result = []; in case you have a proper PHP version.
foreach ($cursor as $document):
  if ( isset( $result[ $document['mac'] ] ) ):
    $result[ $document['mac'] ] += $document['duration']
  else:
    $result[ $document['mac'] ] = $document['duration']
  endif;
endforeach;

You can just replace the endforeach, endif with the traditional brackets.

\$\endgroup\$
1
  • \$\begingroup\$ You shouldn't teach this kind of thing especially in code review. \$\endgroup\$
    – Sede
    Commented Nov 18, 2016 at 13:19
1
\$\begingroup\$

You should not be trying to calculate these sums in PHP. Rather, your MongoDB query should use the $sum aggregator to produce exactly the result you want. The MongoDB code would be faster than PHP, and you would be transferring less irrelevant data as well.

\$\endgroup\$
0
\$\begingroup\$

Since this is such a simple aggregation use case, I would consider aggregating this information in MongoDB rather than in PHP.

As far as code review comments go, I would state that for a simple section of code, it is kind of a mess stylistically. You have:

  • inconsistent indentation
  • poor/inconsistent spacing around operators and flow control characters
  • inconsistent use of single vs. double quotes in specifying array keys
  • poor/inconsistent use of vertical whitespace
\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.