Recursively updating deeply nested arrays in PHP

Recursively updating deeply nested arrays in PHP

Created:14 Jul 2020 11:08:06 , in  Maths

Suppose you have a deeply nested array of items, with its members being numbers and arrays. You want to update all the numbers, like 3 and 5 for example, in all of the arrays, no matter how deep nested the numbers are in the structure.

In this article I look at two methods of recursively updating multilevel arrays using a callback function. First of them utilizes array_walk_recursive built-in PHP function. The other relies on preorder tree traversal technique.

Leveraging array_walk_recursive for updates

The method utilizing array_walk_recursive relies on the function, and as stated above, a user defined callback. The callback function gets applied to every member of an input array as it is visited. Array_walk_recursive enables visiting members of input array in an (almost) effortless manner, so it is used here as a convenient vehicle for traversing the main data structure.

There are two small caveats related to use of array_walk recursive with callback functions, which are worth a mention at this point. Firstly, input to a callback function given to array_walk_recursive should be passed by reference, or changes to the input array will not persist. Secondly, the callback function is not expected to return anything. It is there to modify a value in the required manner and let through what does not need an updated (arguably, a less important point).

Here is an example of how to turn all the 3s to word 'fizz', 5es to word 'buzz' and numbers divisible by both 3 and 5 to word 'fizzbuz' in input array.


// user supplied callback function used by array_walk_recursive to update input array
function fizzBuzzMod(&$item){
    if($item % 3 === 0 and $item % 5 === 0){
      // change sutiable items 
      $item = 'fizzbuzz';
    }elseif ($item % 3 === 0){  
      $item = 'fizz';
    }elseif ($item % 5 === 0){
      $item = 'buzz';
    }
}    

// input array
$items = [1,3,4,10,[15,[30]]];

// update the input array using array_walk_recursive and callback function:
array_walk_recursive($items,'fizzBuzzMod');

// => [1,fizz,4,buzz,[fizzbuzz,[fizzbuzz]]]

Writing your own recursive array updating function

Let's pretend for a while that array_walk recursive does not exist, but you still need to update all the required values, like these divisible by 3, 5 and 3 and 5 in your multilevel array.

One way to do this is as follows:


// leaf updating function
function fizzBuzzMod($item){
  if($item % 3 === 0 and $item % 5 === 0){
    // change sutiable items 
    $item = 'fizzbuzz';
  }elseif ($item % 3 === 0){  
    $item = 'fizz';
  }elseif ($item % 5 === 0){
    $item = 'buzz';
  }
  return $item;
}

// recursive array walking function
function swww_array_walk_recursive($items,$index = 0,$func = 'fizzBuzzMod'){
  
  if(!isset($items[$index])){
    return $items;
  }

  foreach($items as $key => $value){
    if(is_array($items[$key])){
      // go level down if the current $value happens to be an array
      $items[$key] = swww_array_walk_recursive($value);
    }else{
      // apply callback function to modify leaf values
      $items[$key] = call_user_func($func,$value);
    } 
  }
  // return an updated array
  return $items;
}

Let's test it on the input array as follows:


$items = [1,3,[5,[9,[15],7]]];
swww_array_walk_recursive($items);
// => [1,'fizz',['buzz',['fizz',['fizzbuzz'],7]]];

The same underlying principle

Your input array will most likely differ from given in the examples above. Also, almost certainly you will need a different callback function, that is, one which changes $item differently. However, once you have written the latter it will only take passing its name to swww_array_walk_recursive / array_walk recursive to perform an update. Details might change, but principle and more importantly the array walking function remains the same.

Conclusion

People often complain about array_walk_recursive. For many it just seem not to do what they want it to. It might be because the function is not entirely intuitive in terms of how it works and what needs to be done for it to produce desired outcome. If you are one of these who can't bear the array_walk_recursive, you can always write your own recursive array updating function, perhaps something similar to what's given in this article, or if you are too lazy / busy, just grab the one I cobbled together.

This post was updated on 14 Jul 2020 12:05:48

Tags:  php ,  recursion 


Author, Copyright and citation

Author

Sylwester Wojnowski

Author of the above article, Sylwester Wojnowski, enjoys sWWW writing computer code in PHP, JavaScript and BASH, and some other things he wrote more on on the About page of this website.

Copyrights

©Copyright, 2020 Sylwester Wojnowski. This article may not be reproduced or published as a whole or in parts without permission from the author. If you share it, please give author credit and do not remove embedded links.

Computer code, if present in the article, is excluded from the above and licensed under GPLv3.

Citation

Cite this article as:

Wojnowski, Sylwester. "Recursively updating deeply nested arrays in PHP." From sWWW - Code For The Web . https://wojnowski.net.pl//main/index/recursively-updating-deeply-nested-arrays-in-php

Add Comment

Allowed BB Code - style tags: [b][/b], [i][/i], [code=text][/code],[code=javascript][/code],[code=php][/code],[code=bash][/code],[code=css][/code],[code=html][/code]


I constent to processing my data given through this form for purposes of a reply by the administrator of this website.

Recent Comments

Nobody has commented on this post yet. Be first!