2

I have 2 multi-dimensional arrays:

$category = array (
    37 = array (id=1, name=joe, boss=kev)
    73 = array (id=55, name=diane, boss=rox)
    11 = array (id=4, name=bideo, boss=julia)
)  

$other_variable = array (
    1 = array (
        picture1 = array (name=zee, id=4),
        picture2 = array (name=izzy, id=1)
    )
    2 = array (
        picture1 = array (name=foo, id=55),
        picture2 = array (name=ido, id=44)        
    )
    3 = array (
        picture1 = array (name=wheez, id=87),
        picture2 = array (name=ardu, id=9)
    )
)  

I want to combine them so that

$category = array (
    37 = array (
        id=1, 
        name=joe, 
        boss=kev, 
        other_variable = array (
            picture1 = array (name=zee, id=4),
            picture2 = array (name=izzy, id=1)
    ),

    73 = array (
        id=55, 
        name=diane, 
        boss=rox, 
        other_variable = array (
            picture1 = array (name=foo, id=55),
            picture2 = array (name=ido, id=44)
    ),
    11 = array (
        id=4, 
        name=bideo, 
        boss=julia, 
        other_variable = array (
            picture1 = array (name=wheez, id=87),
            picture2 = array (name=ardu, id=9)
    )
)  

I have tried

 $new_array = array_map(null, $category, $other_variable);  

That combines the two arrays, but it creates several nested levels in the array. I am looking for something much cleaner that maintains $category as the parent array.

mickmackusa
  • 43,625
  • 12
  • 83
  • 136
ian
  • 303
  • 3
  • 15

2 Answers2

1

Are you expecting something like this? Here we are using next and current function for incrementing internal pointer of array and getting current value.

Try this code snippet here

foreach($category as &$value)
{
    $value["other_variable"]=current($other_variable);
    next($other_variable);
}
print_r($category);
Sahil Gulati
  • 15,028
  • 4
  • 24
  • 42
1

You were kind of on the right path with your use of array_map() to synchronously iterate two arrays, but sadly that function is going to kill your first level keys.

From the array_map() manual:

The returned array will preserve the keys of the array argument if and only if exactly one array is passed. If more than one array is passed, the returned array will have sequential integer keys.

array_walk() is going to be a cleaner / more appropriate function call for your task of modifying the $category array. array_walk() allows you to modify your $category array and synchronously iterate your $other_variable array (as the optional userdata parameter) without any additional iterated function calls (e.g. next()).

Code: (Demo)

$category=[
    37=>["id"=>1,"name"=>"joe","boss"=>"kev"],
    73=>["id"=>55,"name"=>"diane","boss"=>"rox"],
    11=>["id"=>4,"name"=>"bideo","boss"=>"julia"]
];

$other_variable=[
    1=>["picture1"=>["name"=>"zee","id"=>4],"picture2"=>["name"=>"izzy","id"=>1]],
    2=>["picture1"=>["name"=>"foo","id"=>55],"picture2"=>["name"=>"ido","id"=>44]],
    3=>["picture1"=>["name"=>"wheez","id"=>87],"picture2"=>["name"=>"ardu","id"=>9]]
];

array_walk($category,function(&$v,$k,$ov){$v['other_variable']=current($ov);},$other_variable);
var_export($category);

Output:

array (
  37 => 
  array (
    'id' => 1,
    'name' => 'joe',
    'boss' => 'kev',
    'other_variable' => 
    array (
      'picture1' => 
      array (
        'name' => 'zee',
        'id' => 4,
      ),
      'picture2' => 
      array (
        'name' => 'izzy',
        'id' => 1,
      ),
    ),
  ),
  73 => 
  array (
    'id' => 55,
    'name' => 'diane',
    'boss' => 'rox',
    'other_variable' => 
    array (
      'picture1' => 
      array (
        'name' => 'zee',
        'id' => 4,
      ),
      'picture2' => 
      array (
        'name' => 'izzy',
        'id' => 1,
      ),
    ),
  ),
  11 => 
  array (
    'id' => 4,
    'name' => 'bideo',
    'boss' => 'julia',
    'other_variable' => 
    array (
      'picture1' => 
      array (
        'name' => 'zee',
        'id' => 4,
      ),
      'picture2' => 
      array (
        'name' => 'izzy',
        'id' => 1,
      ),
    ),
  ),
)

Late Edit:

Additional methods that modify the $other_variable array (effectively empty it when the iterative process resolves) include:

$category=array_map(function($v)use(&$other_variable){
    return $v+=['other_variable'=>array_shift($other_variable)];
},$category);

and

foreach($category as &$value){
    $value["other_variable"]=array_shift($other_variable);
}

Obviously, these methods should only be used if you do not intend to use $other_variable down script or you are going to declare a copy of the array for later use.

mickmackusa
  • 43,625
  • 12
  • 83
  • 136
  • Thanks @mickmackusa. array_walk ends up being slightly slower than Sahil Gulati's answer in my example (0.008 seconds vs 0.00043 seconds). – ian Nov 28 '17 at 02:25
  • Interesting. Thanks for that feedback. This is not unexpected because loops often outperform functional programming. Only when array sizes become large have I seen functional iterators output perform simple loops. – mickmackusa Nov 28 '17 at 02:25
  • If you are going to use a "Pass by Reference" `&$value` technique on the global scope, it is advised to `unset(&$value);` when you are done with it so that it doesn't interfere with any of your processes "down script". – mickmackusa Nov 28 '17 at 02:31
  • No problem. Does this apply to the other example I am working on, i.e. for smaller arrays the array_search may be faster while for larger, your iterator solution is best? – ian Nov 28 '17 at 02:31
  • The losses in efficiency (while performing iterated `array_search()`es on your other question will be reduced as the array shrink in size, but I don't expect those occurrences (when both arrays are relatively small) to be noticeable in the slightest to the user. – mickmackusa Nov 28 '17 at 02:34
  • @ian Wait a second, I just ran my own tests and mine was faster. I think your benchmarking may have had some caching influencing the results. See these demos: Sahil's is `.081` https://3v4l.org/Rlbd5/perf#output and mine is `.047` https://3v4l.org/0oGNW/perf#output These numbers will fluctuate slightly each time, and you will find them to be relatively close with the small size of the arrays. I am more interested in promoting that my answer uses a feature of `array_walk()` that was designed for your task. – mickmackusa Nov 28 '17 at 02:39
  • OK. I ran the tests several times and returned the same results. I will test it again when I finish with the current task. – ian Nov 28 '17 at 02:44