如何访问array_reduce中的当前索引?

时间:2019-01-18 17:15:55

标签: php

已经阅读了SO post,在PHP中,我知道您可以使用index这样的迭代方式来获得array_map

array_map(function($item, $index) { ... }, $items, array_keys($items));

当我使用$index时如何获得array_reduce可用的密码?我尝试过:

array_reduce($items, array_keys($items), function($acc, $item, $index) { ... }, array());

array_reduce($items, function($acc, $item, $index) { ... }, array(), array_keys($items));

但是我似乎仍然无法在$index中获得array_reduce。以前有人成功做到过吗?

编辑

关于我为什么要问这个问题的一些背景。

我不想使用foreach,因为我必须对foreach之外的数组进行突变才能创建我的收藏集。我宁愿避免突变。

其他语言允许人们使用reduce并访问JavaScriptRuby中的当前索引。我希望在PHP中获得相同的功能。那好吧!看起来我将不得不使用foreach创建数组,同时还要使当前索引处于迭代状态。

6 个答案:

答案 0 :(得分:2)

您对array_reduce中的获取索引的了解不存在。 Check documentation.

问题是为什么

看,reduce用于降低到单个值的目的,它是聚合。您具有初始值,而下一个值则显示了减少策略。了解当前项目索引毫无意义。

在某些其他语言中,它们可能提供当前索引,但在PHP中不提供此索引array_reduce。它是语言和功能设计的,在实现上有一些限制。

但这并不意味着您无法拥有它。您可以使用它,但不能通过回调!

$i = 0;
$data = [1, 2, 3, 4];

// (1) 
$result = array_reduce($data, function ($c, $i) { return $c + $i; }, 0);

// (2)
array_reduce($data, function ($c, $i) { echo "$i\n"; $i++; return $c + $i; }, 0);

问题是,该函数旨在实现此目的。或者您正在尝试使用错误的功能。您可能正在寻找其他一些功能。

或者您也可以编写一个实现该功能的函数:)

答案 1 :(得分:1)

PHP中的数组是奇特的东西:它们可以用作列表,队列,字典,集合,有序字典以及各种其他多值结构。但是,大多数函数在编写时都考虑了其中一种或两种结构。

对于array_reduce,该数组被视为 list -项目的有序集合。因此,数组的 keys 不会传递给回调。这对于常见情况来说很有意义,例如计算总数或平均值等。

毫无疑问,在某些情况下,您希望减少键-值对的有序字典;不幸的是,PHP没有为此提供功能。

另一方面,有两个相关的功能可能可以代替使用:

  • array_map,它在每个元素上运行回调,并生成一个新数组,其中一个输入项对应一个输入项
  • array_walk,它在每个元素上运行回调并忽略结果,但可以通过引用获取第三个参数,从而可以累积副作用

这三个函数也可以通过foreach循环轻松实现,因此您可以编写自己的reduce函数,例如( unested ):

function array_reduce_assoc(array $array, callable $callback, $initial=null) {
    $carry = $initial;
    foreach ( $array as $key => $value ) {
        $carry = $callback($carry, $key, $value);
    }
}

答案 2 :(得分:1)

You already know you how to get the index in array_map, so you could use that to reduce instead if you like. Just use a reference to the "carry" variable in the callback.

$example = ['a' => 1, 'b' => 2, 'c' => 3];

array_map(function($key, $value) use (&$reduced) {
    $reduced .= "$key$value";  // for example
}, array_keys($example), $example);

echo $reduced;  //a1b2c3

I'm not sure I see the advantage of this over foreach, but it's another possible way to do it.

答案 3 :(得分:0)

<?php
$data = ['one', 'two', 'three'];

$result = array_reduce($data, function($carry, $item){
    $carry['out'] .= $carry['i'] . ') '. $item . '; ';
    $carry['i']++;
    return $carry;
}, ['out' => '', 'i' => 1] )['out'];

echo $result; // 1) one; 2) two; 3) three;

答案 4 :(得分:0)

我只是遇到了同样的问题。解决起来很简单。

$i = 0;
$p = array_reduce($array, function($output, $item) use (&$i) {
   // use $i
   // do something with $item and/or $output
   $i++; // increment $i
   return $output;
}, $initial);

&$i通过$i作为参考,并授予它更新的权利。

答案 5 :(得分:0)

这类似于another answer,但有几点不同。

首先,另一个答案提供了一个示例,但不是完整的示例。还有 其他答案将回调参数定义为$carry, $key, $value。我觉得 $carry, $value, $key会更好,因为它会匹配 JavaScript reduce

它还会保留PHP自己的array_reduce的顺序,而只是添加 一个额外的争论。在我的示例中,我正在实现array_flip, 证明可能的事:

<?php
$a = ['May', 'June'];
$m = [];

$f = function ($m_acc, $s_cur, $n_idx) {
   return $m_acc + [$s_cur => $n_idx];
};

foreach ($a as $n => $s) {
   $m = $f($m, $s, $n);
}

print_r($m);