Search code examples
phpforeachfunctional-programmingarray-map

Refactoring a foreach to functional programming


I'm refactoring some code to functional programming for readability and I encounter a problem with an array. I want to change an array of objects to a simple array with arrays of values.

The first array looks like this:

array(2) {
  [5701]=>
  object(stdClass)#123 (3) {
    ["id"]=>
    string(4) "5701"
    ["username"]=>
    string(6) "s67688"
    ["state"]=>
    string(6) "Inactive"    
  }
  [5762]=>
  object(stdClass)#136 (3) {
    ["id"]=>
    string(4) "5762"
    ["username"]=>
    string(6) "s67701"
    ["state"]=>
    string(6) "Active"
  }  
}

I want to convert it into something like this:

array(2) {
  [0]=>
  array(3) {
    [0]=>
    id(4) 5701
    [1]=>
    string(6) "s67688"
    [2]=>
    string(8) "Inactive"    
  }
  [1]=>
  array(3) {
    [0]=>
    int(4) 5762
    [1]=>
    string(6) "s67701"
    [2]=>
    string(8) "Active"    
  }
}

With a simple foreach it is easy to achieve but when i try the following code:

$newArr = array_map(function($value){
               return array_values(get_object_vars($value));
          }, $baseArr);

The output is the following:

array(2) {
  [5701]=>
  array(3) {
    [0]=>
    id(4) 5701
    [1]=>
    string(6) "s67688"
    [2]=>
    string(8) "Inactive"    
  }
  [5762]=>
  array(3) {
    [0]=>
    int(4) 5762
    [1]=>
    string(6) "s67701"
    [2]=>
    string(8) "Active"    
  }
}

As you can see the base array keys are not changing, why is this happening?

This is the original foreach which returns what i want:

$newArr = [];
foreach ($baseArr as $value) {
     $newArr[] = array_values(get_object_vars($user));
}

I've also tried array_walk.


Solution

  • array_map applies a callback to the values and does not modify the keys. I also simplified getting the values by just casting to array:

    $newArr = array_values(array_map(function($v){
                                         return array_values((array)$v);
                                     }, $baseArr));
    

    You can use the array_values after as above, or before:

    $newArr = array_map(function($v){
                            return array_values((array)$v);
                        }, array_values($baseArr));
    

    I personally would keep it as an associative array:

    $newArr = array_values(array_map(function($v){ return (array)$v; }, $baseArr));