Search code examples
phpmapreduceassociative-array

array_reduce() can't work as associative-array "reducer" for PHP?


I have an associative array $assoc, and need to reduce to it to a string, in this context

$OUT = "<row";
foreach($assoc as $k=>$v) $OUT.= " $k=\"$v\"";
$OUT.= '/>';

How to do in an elegant way the same thing, but using array_reduce()


Near the same algorithm (lower performance and lower legibility) with array_walk() function,

 array_walk(  $row, function(&$v,$k){$v=" $k=\"$v\"";}  );
 $OUT.= "\n\t<row". join('',array_values($row)) ."/>";

Ugly solution with array_map() (and again join() as reducer):

  $row2 = array_map( 
    function($a,$b){return array(" $a=\"$b\"",1);},
    array_keys($row),
    array_values($row)
  ); // or  
  $OUT ="<row ". join('',array_column($row2,0)) ."/>";

PS: apparently PHP's array_reduce() not support associative arrays (why??).


Solution

  • First, array_reduce() works with associative arrays, but you don't have any chance to access the key in the callback function, only the value.

    You could use the use keyword to access the $result by reference in the closure like in the following example with array_walk(). This would be very similar to array_reduce():

    $array = array(
        'foo' => 'bar',
        'hello' => 'world'
    );
    
    // Inject reference to `$result` into closure scope.
    // $result will get initialized on its first usage.
    array_walk($array, function($val, $key) use(&$result) {
        $result .= " $key=\"$val\"";
    });
    echo "<row$result />";
    

    Btw, imo your original foreach solution looks elegant too. Also there will be no significant performance issues as long as the array stays at small to medium size.