繁体   English   中英

array_reduce() 不能作为 PHP 的关联数组“reducer”?

[英]array_reduce() can't work as associative-array “reducer” for PHP?

我有一个关联数组$assoc ,在这种情况下需要将其缩减为一个字符串

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

如何以优雅的方式做同样的事情,但使用array_reduce()


array_walk()函数接近相同的算法(较低的性能和较低的易读性),

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

使用array_map()丑陋解决方案(再次join()作为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:显然 PHP 的array_reduce()不支持关联数组(为什么?? )。

首先, array_reduce()与关联数组一起工作,但您没有机会访问回调函数中的键,只能访问值。

您可以使用use关键字通过闭包中的引用访问$result ,如下面的array_walk()示例所示。 这与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 />";

顺便说一句,您原来的 foreach 解决方案看起来很优雅 此外,只要阵列保持在中小型规模,就不会有显着的性能问题。

$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()));

我个人认为 foreach 没有任何问题,但是如果你想要一个单一的表达,你的map片段可以简化为

$OUT = sprintf("<row %s/>",
    join(" ", array_map(
        function($a, $b) { return "$a=\"$b\""; },
        array_keys($assoc),
        array_values($assoc)
)));

此外,由于您正在生成 XML,因此最好使用专用工具,例如:

$doc = new SimpleXMLElement("<row/>");
foreach($assoc as $k => $v)
    $doc->addAttribute($k, $v);
echo $doc->asXML();

您可以使用array-chunk准备输入数组,并像这样使用 array_reduce:

$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;
   }, "");

将显示 - 数组作为文本表示的理想选择:

a = 123
b = 234
c = 55

array_chunk 将创建单个关联数组条目的数组。 请注意,这可能不是性能最高的解决方案 - 只是一个相当短的解决方案。

如果您在array_reduce上设置,并且数组的值是唯一的,那么您可以通过将关联数组传递给回调函数并使用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);
}, '');

我个人觉得在这种情况下使用array_mapjoin会更有效。

$OUT .= join(' ', array_map(function($v, $k){
    return sprintf('%s="%s"', $k, $v);
}, $assoc, array_keys($assoc)));

严格使用array_reduce这是我能想到的最简单的算法(两个匿名函数都是纯函数):

$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]}\"";  }
        )
    .' />';

在一行...

$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]}\""; }).' />';
$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;

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM