有没有办法做array_map但作为迭代器?
例如:
foreach (new MapIterator($array, $function) as $value)
{
if ($value == $required)
break;
}
这样做的原因是$ function很难计算,而$ array有太多元素,只需映射直到找到特定值。 array_map将在我搜索我想要的值之前计算所有值。
我可以自己实现迭代器,但我想知道是否有本地方法来执行此操作。我找不到任何搜索PHP文档的内容。
答案 0 :(得分:6)
简而言之:否。
PHP中没有内置的延迟迭代器映射。有一个非惰性函数 iterator_apply(),但没有你喜欢的那样。
如你所说,你可以自己写一个。我建议你扩展 IteratorIterator ,然后简单地覆盖 current()方法。
答案 1 :(得分:5)
这是一个懒惰的集合地图函数,可以返回Iterator
:
/**
* @param array|Iterator $collection
* @param callable $function
* @return Iterator
*/
function collection_map( $collection, callable $function ) {
foreach( $collection as $element ) {
yield $function( $element );
}
}
答案 2 :(得分:1)
我正在考虑一个简单的Map类实现,它使用一组键和一组值。整个实现可以像Java的Iterator类一样使用,而你可以像:
一样遍历它while ($map->hasNext()) {
$value = $map->next();
...
}
答案 3 :(得分:0)
foreach ($array as $key => $value) {
if ($value === $required) {
break;
} else {
$array[$key] = call_back_function($value);
}
}
处理并迭代直到找到所需的值。
答案 4 :(得分:0)
请勿使用迭代器,答案是:
foreach ($array as $origValue)
{
$value = $function($origValue);
if ($value == $required)
break;
}
答案 5 :(得分:0)
我写了这个类来为此目的使用回调。用法:
$array = new ArrayIterator(array(1,2,3,4,5));
$doubles = new ModifyIterator($array, function($x) { return $x * 2; });
定义(随意根据您的需要进行修改):
class ModifyIterator implements Iterator {
/**
* @var Iterator
*/
protected $iterator;
/**
* @var callable Modifies the current item in iterator
*/
protected $callable;
/**
* @param $iterator Iterator|array
* @param $callable callable This can have two parameters
* @throws Exception
*/
public function __construct($iterator, $callable) {
if (is_array($iterator)) {
$this->iterator = new ArrayIterator($iterator);
}
elseif (!($iterator instanceof Iterator))
{
throw new Exception("iterator must be instance of Iterator");
}
else
{
$this->iterator = $iterator;
}
if (!is_callable($callable)) {
throw new Exception("callable must be a closure");
}
if ($callable instanceof Closure) {
// make sure there's one argument
$reflection = new ReflectionObject($callable);
if ($reflection->hasMethod('__invoke')) {
$method = $reflection->getMethod('__invoke');
if ($method->getNumberOfParameters() !== 1) {
throw new Exception("callable must have only one parameter");
}
}
}
$this->callable = $callable;
}
/**
* Alters the current item with $this->callable and returns a new item.
* Be careful with your types as we can't do static type checking here!
* @return mixed
*/
public function current()
{
$callable = $this->callable;
return $callable($this->iterator->current());
}
public function next()
{
$this->iterator->next();
}
public function key()
{
return $this->iterator->key();
}
public function valid()
{
return $this->iterator->valid();
}
public function rewind()
{
$this->iterator->rewind();
}
}
答案 6 :(得分:0)
PHP的迭代器使用起来非常麻烦,特别是在需要深度嵌套的情况下。 LINQ对数组和对象实现类似SQL的查询,因此更适合这种情况,因为它允许简单的方法链接并且一直是懒惰的。其中一个实现它的库是YaLinqo *。有了它,您可以像这样执行映射和过滤:
// $array can be an array or \Traversible. If it's an iterator, it is traversed lazily.
$is_value_in_array = from($array)->contains(2);
// where is like array_filter, but lazy. It'll be called only until the value is found.
$is_value_in_filtered_array = from($array)->where($slow_filter_function)->contains(2);
// select is like array_map, but lazy.
$is_value_in_mapped_array = from($array)->select($slow_map_function)->contains(2);
// first function returns the first value which satisfies a condition.
$first_matching_value = from($array)->first($slow_filter_function);
// equivalent code
$first_matching_value = from($array)->where($slow_filter_function)->first();
还有更多功能,总体超过70种。
*由我开发
答案 7 :(得分:0)
看看Non-standard PHP library。它有一个lazy map函数:
use function \nspl\a\lazy\map;
$heavyComputation = function($value) { /* ... */ };
$iterator = map($heavyComputation, $list);