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)) ."/>";
Ugly 解决方案 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 解决方案看起来也很优雅。此外,只要阵列保持在中小尺寸,就不会有明显的性能问题。
我个人认为 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 = 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()));
严格使用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]}\""; }).' />';
您可以使用 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
.[= 来访问密钥16=]
// 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_map
和 join
在这种情况下会更有效。
$OUT .= join(' ', array_map(function($v, $k){
return sprintf('%s="%s"', $k, $v);
}, $assoc, array_keys($assoc)));
我有一个关联数组 $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)) ."/>";
Ugly 解决方案 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 解决方案看起来也很优雅。此外,只要阵列保持在中小尺寸,就不会有明显的性能问题。
我个人认为 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 = 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()));
严格使用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]}\""; }).' />';
您可以使用 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
.[= 来访问密钥16=]
// 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_map
和 join
在这种情况下会更有效。
$OUT .= join(' ', array_map(function($v, $k){
return sprintf('%s="%s"', $k, $v);
}, $assoc, array_keys($assoc)));