gpt4 book ai didi

php - 在 PHP 中模拟 ruby​​ 的 inject() 行为

转载 作者:可可西里 更新时间:2023-11-01 00:52:55 25 4
gpt4 key购买 nike

从这个问题here ,我正在编写一个枚举包装器,以包含一些可与 lambda 一起使用的方法,以在某种程度上模拟 ruby​​ 在枚举中使用 block 。

class enum {
public $arr;

function __construct($array) {
$this->arr = $array;
}

function each($lambda) {
array_walk($this->arr, $lambda);
}

function find_all($lambda) {
return array_filter($this->arr, $lambda);
}

function inject($lambda, $initial=null) {
if ($initial == null) {
$first = array_shift($this->arr);
$result = array_reduce($this->arr, $lambda, $first);
array_unshift($this->arr, $first);

return $result;
} else {
return array_reduce($this->arr, $lambda, $initial);
}
}

}


$list = new enum(array(-1, 3, 4, 5, -7));
$list->each(function($a) { print $a . "\n";});

// in PHP you can also assign a closure to a variable
$pos = function($a) { return ($a < 0) ? false : true;};
$positives = $list->find_all($pos);

现在,我该如何实现 inject()尽可能优雅?


编辑: 方法实现如上所示。使用示例:

// inject() examples 
$list = new enum(range(5, 10));

$sum = $list->inject(function($sum, $n) { return $sum+$n; });
$product = $list->inject(function($acc, $n) { return $acc*$n; }, 1);

$list = new enum(array('cat', 'sheep', 'bear'));
$longest = $list->inject(function($memo, $word) {
return (strlen($memo) > strlen($word)) ? $memo : $word; }
);

最佳答案

我不熟悉Ruby,但从描述来看,它似乎类似于array_reduce .

mixed array_reduce ( array $input , callback $function [, mixed $initial = NULL ] )

array_reduce() applies iteratively the function function to the elements of the array input, so as to reduce the array to a single value.

除了“reduce”之外,这个操作有时也被称为"fold" ;在 Mathematica 中:

Fold[f, init, {a, b, c, d}] == f[f[f[f[init, a], b], c], d]

The second form uses the first element of the collection as a the initial value (and skips that element while iterating).

第二种形式可以这样实现:

//$arr is the initial array
$first = array_shift($arr);
$result = array_reduce($arr, $callback, $first);

对姆拉登的回应

PHP 中的数组函数不能那样使用,因为它们只能处理数组,不能处理任意对象。

这里有几个选项:

  • 您可以在将对象传递给 array_reduce 之前将其转换为数组。实际上,这没有太大值(value),因为转换包括创建一个以对象属性作为元素的数组。此行为只能在内部更改(编写 native 扩展)。
  • 您可以让您的所有对象实现一个带有方法toArray 的接口(interface),在将它传递给array_reduce 之前必须调用该方法。也不是个好主意。
  • 您可以实现一个适用于任何Traversable 对象的array_reduce 版本。这很容易做到,但您不能在函数声明中放置 Traversable 类型提示,因为数组不是对象。有了这样的提示,每个数组都必须在函数调用之前封装在 ArrayIterator 对象中。

关于php - 在 PHP 中模拟 ruby​​ 的 inject() 行为,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3329556/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com