1

In PHP, what is quickest way to turn the following array variables:

$id = [11,12,13];
$code = ['1234','5678','9012'];
$qty = [3,4,5];
$amount = [12.34,23.45,34.56];

Into an array of associative arrays, like the following:

[
  ['id'=>11,'code'=>'1234','qty'=>3,'amount'=>12.34],
  ['id'=>12,'code'=>'5678','qty'=>4,'amount'=>23.45],
  ['id'=>13,'code'=>'9012','qty'=>5,'amount'=>34.56],
]

Currently, I'm doing the following to convert the data.

$max = count($id);
$data = [];
for ($i=0; $i<$max; $i++) {
  $data[] = [
    'id' => $id[$i],
    'code' => $code[$i],
    'qty' => $qty[$i],
    'amount' => $amount[$i]
  ];
}

My application does this a lot, and looking if there are ways to decrease processing time.
Currently using PHP version 5.6

user3720435
  • 1,421
  • 1
  • 17
  • 27
  • 4
    I'm quite sure what you have is the fastest way. But how does the values end up in those variables? That may be the key to make it faster – Andreas Jan 06 '20 at 05:02
  • User you have a few answers with various quality. The best way to optimize is to start as early as possible with the optimization. As I wrote earlier, add to your question how the arrays start their lives. – Andreas Jan 06 '20 at 07:32

3 Answers3

4

foreach is typically the fastest method of the "general" approaches used to accomplish your desired end-results. This is due to the count() call prior to issuing for() accompanied with an incremental variable to determine the size and placement of the array to iterate over.

Benchmarks: https://3v4l.org/ejIl5
Benchmark 1-5000 https://3v4l.org/IOlAm

$data = [];
foreach($id as $i => $v) {
    $data[] = [
        'id' => $v,
        'code' => $code[$i],
        'qty' => $qty[$i],
        'amount' => $amount[$i]
    ];
}
//Execution time: ~0.00000200 seconds
$max = count($id);
$data = [];
for ($i=0; $i<$max; $i++) {
  $data[] = [
    'id' => $id[$i],
    'code' => $code[$i],
    'qty' => $qty[$i],
    'amount' => $amount[$i]
  ];
}
//Execution time ~0.00000600 seconds

array_map was the slowest

$data = array_map(function($a, $b, $c, $d) {
    return [
        'id' => $a,
        'code' => $b,
        'qty' => $c,
        'amount' => $d
    ];
}, $id, $code, $qty, $amount);
//Execution time: ~0.00001000 seconds

The benchmark used executes a dry-run for each of the approaches to reduce OP code optimization issues that would typically be implemented in a production environment.


As an added bonus from the "general" approaches, I also ran a benchmark of an optimized version of the double-ended iteration approach (for ($i=0; $i<ceil($max/2); $i++)). https://3v4l.org/KHUul and 1-5000 https://3v4l.org/Mg95n which had wildly different values with the smaller array sizes, ranging from 0.00030208 seconds to 0.00000095 seconds, but on average was slower than the general for() loop.

As with any benchmarks, the results may vary for your particular environment, settings and are only meant to serve as a generalization of what could be. Please be sure to benchmark your preferred methods in your specific environment to determine which is best.

Will B.
  • 17,883
  • 4
  • 67
  • 69
1

you can use foreach as well. I am not sure it will more efficient way but it can help you.

    $id = [11,12,13];
    $code = ['1234','5678','9012'];
    $qty = [3,4,5];
    $amount = [12.34,23.45,34.56];
    foreach ($id as $key=>$val)
    {
        $array[$key]["id"]= $val;
        $array[$key]["code"]= $code[$key];
        $array[$key]["qty"]= $qty[$key];
        $array[$key]["amount"]= $amount[$key];
    }
Amit Sharma
  • 1,775
  • 3
  • 11
  • 20
0

My below code will optimize the loop by reducing the loop execution to half and will gives your expected result.

$id     = [11,12,13,56,34,23,34];
$code   = ['1234','5678','9012','4343','4543','4642','534'];
$qty    = [3,4,5,6,7,8,3];
$amount = [12.34,23.45,34.56,66.34,75.32,54.3,23.2];


$max = count($id);
$loopRun = 0;
$data = [];
$halfCount = ceil($max/2);
for ($i=0; $i < $halfCount; $i++) {
  $loopRun++;
  $data[$i] = [
    'id'        => $id[$i],
    'code'      => $code[$i],
    'qty'       => $qty[$i],
    'amount'    => $amount[$i]
  ];

  $data[$max-($i+1)] = [
    'id'        => $id[$max-($i+1)],
    'code'      => $code[$max-($i+1)],
    'qty'       => $qty[$max-($i+1)],
    'amount'    => $amount[$max-($i+1)]
  ];
}
echo "Loop Run Count : ".$loopRun."<br>";
ksort($data);

Demo Link

Ajith
  • 2,476
  • 2
  • 17
  • 38
  • 3
    I don’t think the number of loop iterations is fundamentally the problem here; whether you process two entries in one iteration or one entry per iteration doesn’t fundamentally change the number of entries needing to be processed. In fact you’re adding an entirely new costly operation with `ksort`. At least provide a benchmark that proves that this makes any sense to use at all! – deceze Jan 06 '20 at 05:46
  • @deceze Run time will be less if we reduce the loop to half for example if iteration for 1000 time takes 10 sec then the iteration for 500 times will take only 5 sec . we can consider this for large inputs only. I have checked that with large inputs and my concept does work for me. – Ajith Jan 06 '20 at 06:01
  • 1
    Prove it with a benchmark! – deceze Jan 06 '20 at 06:02
  • @deceze The following link is a proof for my concept https://3v4l.org/EG7Gr , As I mention it will make a difference for larger loops only – Ajith Jan 06 '20 at 06:18
  • 1
    Yeah, wow, if you take all the actual processing out of the loop then a loop with half as many iterations sure is faster… ‍♂️ – deceze Jan 06 '20 at 06:21
  • since `ceil()` is being called from within the `for()` statement, it will be executed on each iteration of the array. I recommend moving above like `count()` to further improve performance. – Will B. Jan 06 '20 at 06:35
  • @deceze You are a genius! ... Multiple assignment doest take time but the processing `$max-($i+1)` does take time in loop. ie if I add `$data[$i]` 2 tymes, my answer is optimized. but `$data[$max-($i+1)]` is not optimized. – Ajith Jan 06 '20 at 06:56
  • 1
    This code is not optimized in any way at all. It's the same amount of items that is processed. But what happens if the count is 3? Your code will break – Andreas Jan 06 '20 at 06:59
  • @Andreas Count 3 wont break – Ajith Jan 06 '20 at 07:00
  • Sorry not break but it will process the same number twice. – Andreas Jan 06 '20 at 07:02