可以将文章内容翻译成中文,广告屏蔽插件可能会导致该功能失效(如失效,请关闭广告屏蔽插件后再试):
问题:
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??).
回答1:
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 it's first usage.
array_walk($array, function($key, $val) use(&$result) {
$result .= "$key=\"$val\"";
});
echo $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.
回答2:
$array = array(
'foo' => 'bar',
'hello' => 'world'
);
$OUT = join(" ", array_reduce(array_keys($array), function($as, $a) use ($array) {
$as[] = sprintf('%s="%s"', $a, $array[$a]); return $as;
}, array()));
回答3:
I personally see nothing wrong with the foreach thing, but if you want one single expression, your map
snippet can be simplified down to
$OUT = sprintf("<row %s/>",
join(" ", array_map(
function($a, $b) { return "$a=\"$b\""; },
array_keys($assoc),
array_values($assoc)
)));
Also, since you're generating XML, it's better to use a dedicated tool, for example:
$doc = new SimpleXMLElement("<row/>");
foreach($assoc as $k => $v)
$doc->addAttribute($k, $v);
echo $doc->asXML();
回答4:
you can prepare your input array using array-chunk and use array_reduce like this:
$a = ["a" => 123, "b" => 234, "c" => 55];
echo array_reduce(
array_chunk($a, 1, true),
function ($r, $i) {
return $r . key($i) ." = ". current($i) . PHP_EOL;
}, "");
will show - ideal for array-as-text representation:
a = 123
b = 234
c = 55
array_chunk will create an array of single associative array entries. please note that is is probably not the the most performant solution - just a rather short one.
回答5:
If you are set on array_reduce
, and the values of your array are unique, then you can access the key by passing the associative array to the callback function and using array_search
.
// Pass $assoc to your anonymous function and use array_search to get the key.
$OUT .= array_reduce($assoc, function($o, $v) use($assoc) {
return sprintf('%s %s="%s"', $o, array_search($v, $assoc), $v);
}, '');
Personally, I feel that array_map
and join
would be more effective in this situation.
$OUT .= join(' ', array_map(function($v, $k){
return sprintf('%s="%s"', $k, $v);
}, $assoc, array_keys($assoc)));
回答6:
Strictly using array_reduce this is the simplest algorithm I can think of (also both anonymous functions are pure functions):
$out =
'<row '.
array_reduce(
array_map (
function ($e, $k) { return [$e, $k]; },
array_keys($assoc),
$assoc
),
function ( $props, $e ) { return $props." {$e[0]}=\"{$e[1]}\""; }
)
.' />';
In one line...
$out = '<row '. array_reduce( array_map( function ($e, $k) { return [$e, $k]; }, array_keys($assoc), $assoc), function ( $props, $e ) { return $props." {$e[0]}=\"{$e[1]}\""; }).' />';
回答7:
$ar = array(
array("month"=>'8', "revenue"=>300),
array("month"=>'2',"revenue"=>500),
array("month"=>'10',"revenue"=>100),
array("month"=>'3',"revenue"=>200),
array("month"=>'5',"revenue"=>600)
);
// where $a stores the result and $b is the new element of the array to add
function reduce_target_ar($a,$b){
return $a + $b['revenue'];
}
$sum = array_reduce($ar,"reduce_target_ar");
echo $sum;