5
\$\begingroup\$

The purpose of this code is to change each column to a row, and assign keys to each value for the new array according to the old array. I would like to know if there're other ways to optimize it.

<?php

$arr = [
    'name' => ['a', 'b', 'c'],
    'age'  => [ 2 ,  1 ,  3 ]
];

$result = [];
$keys   = array_keys($arr);
foreach($arr[$keys[0]] as $index => $temp) {
    $data = [];
    foreach($keys as $i => $key) {
        $data[$key] = $arr[$key][$index];
    }
    $result[] = $data;
}

print_r($result);

Which gives:

$result = [
    ['name' => 'a', 'age' => 2],
    ['name' => 'b', 'age' => 1],
    ['name' => 'c', 'age' => 3],
];
\$\endgroup\$
1
\$\begingroup\$

Like you, I don't see a better way than basing the method on evaluating array_keys($arr), then iterate it to build each new member.

But there are two possible slight improvement in how to it:

$arr = [
    'name' => ['a', 'b', 'c'],
    'age'  => [ 2 ,  1 ,  3 ]
];

$result = [];
$keys = array_keys($arr);
for ($row = 0,  $rows = count(reset($arr)); $row < $rows; $row++) {
  foreach ($keys as $key) {
    $result[$row][$key] = $arr[$key][$row];
  }
}

echo '<pre>' . print_r($result, true) . '</pre>';

The first (and somewhat obvious) improvement is: not to use intermediary variable data.

I'm not really sure of the second one: I tend to think that the for() loop will be faster, because it accesses $arr only once (count(reset($arr))), while the foreach() loop have to extract data from $arr on each step.

\$\endgroup\$
1
\$\begingroup\$

There isn't really any great performance improvement to be made here in my opinion. You original structure is going to require nested loop approach to generate your desired structure regardless.

My only suggestion would be building an array of objects in your result rather than an array of associative arrays, as I think what you have shown in your example is more meaningful as objects (i.e. items that have a set of properties) vs. as an associative array (which I typically like to use more for hashmap type of use cases).

\$\endgroup\$
1
\$\begingroup\$

If you would like to avoid the nested loop structure, yet have a dynamic method that will permit key name changes and increases in "rows" and "columns" with just one loop, then array_column() and array_combine() are useful:

Code: (Demo)

$arr = [
    'name' => ['a', 'b', 'c', 'd'],
    'age'  => [ 2 ,  1 ,  3 ,  4 ],
    'shoe' => [11 ,  9 ,  8 , 10 ],
    'kids' => [ 1 ,  0 ,  2 ,  3 ]
];
$keys = array_keys($arr);
foreach ($arr[$keys[0]] as $k => $v) {  // only iterate first "row"
    $result[] = array_combine($keys, array_column($arr, $k));  // store each "column" as an associative "row"
}
var_export($result);

Output:

array (
  0 => 
  array (
    'name' => 'a',
    'age' => 2,
    'shoe' => 11,
    'kids' => 1,
  ),
  1 => 
  array (
    'name' => 'b',
    'age' => 1,
    'shoe' => 9,
    'kids' => 0,
  ),
  2 => 
  array (
    'name' => 'c',
    'age' => 3,
    'shoe' => 8,
    'kids' => 2,
  ),
  3 => 
  array (
    'name' => 'd',
    'age' => 4,
    'shoe' => 10,
    'kids' => 3,
  ),
)
\$\endgroup\$
0
\$\begingroup\$

You can use normal for loop like this :

<?php

  $arr = [
'name' => ['a', 'b', 'c'],
'age'  => [ 2 ,  1 ,  3 ]
 ];

 $new_array=array();
 $acount=count($arr['name']);

 for($i=0;$i<$acount;$i++){

 $new_array[$i]['name']=$arr['name'][$i];

 $new_array[$i]['age']=$arr['age'][$i];

 }


?>
\$\endgroup\$
  • 1
    \$\begingroup\$ You certainly could do that. Why would you want to do so? In particular, note that the original code handled arbitrary array keys. You're manually specifying each key, so you'd have to rewrite the code for each task. So you should show some advantage to this code that outweighs the flexibility of the original code. In general, remember that we are Code Review. Why we make decisions in our code is as important as the code itself. \$\endgroup\$ – mdfst13 Oct 25 '16 at 15:07
0
\$\begingroup\$

If you have 2 attributes: name, age and unique name, may be helpful I think)

$userData = array_combine($arr['name'], $arr['age']);

foreach($userData as $name => $age) { }
\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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