web-dev-qa-db-ja.com

array_reduce()は、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()は連想配列をサポートしていません(why ??)。

14
Peter Krauss

まず、array_reduce()は連想配列で機能しますが、値だけがコールバック関数のキーにアクセスすることはできません。

useキーワードを使用すると、次のarray_walk()の例のように、クロージャ内の参照によって_$result_にアクセスできます。これは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($val, $key) use(&$result) {
    $result .= "$key=\"$val\"";
});
echo $result;
_

ところで、元のforeachソリューションのimo エレガントに見えるも。また、アレイが小規模から中規模のサイズである限り、パフォーマンスに大きな問題はありません。

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

私は個人的にはforeachに問題はないと思いますが、1つの式が必要な場合は、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();
5
georg

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は、単一の連想配列エントリの配列を作成します。これはおそらく最も高性能なソリューションではないことに注意してください-かなり短いソリューションです。

2
Andy P

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)));
1
Shaun Cockerill

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