spencerwi/lazylist

PHP >=7.4 的懒列表(fused-streams/generators)库

1.0.0 2021-06-23 00:33 UTC

This package is auto-updated.

Last update: 2024-09-23 07:33:06 UTC


README

PHP 的懒列表(或生成器,或融合流,或 seq,或其他)库。

支持 PHP >=7.4。

用法

创建

懒列表可以从数组创建

$lazyList = \Spencerwi\Lazy_list\LazyList::fromArray([1,2,3,4,5]);

它们也可以从接受一个 int 索引并返回某个值或返回 \Spencerwi\Lazy_list\LazyList::STOP_ITERATION 来表示列表结束的函数创建。

$lazyList2 = new \Spencerwi\Lazy_list\LazyList(function(int $i) {
    if ($i < 10) {
        return $i;
    } else {
        return \Spencerwi\Lazy_list\LazyList::STOP_ITERATION;
    }
});
// This amounts to a LazyList containing [0,1,2,3,4,5,6,7,8,9].

map

你可以映射一个懒列表,并且它是一个“懒”映射,所以它不会在真正强制评估列表之前调用你的映射函数。

$mapperWasCalled = false;
$squares = $lazyList->map(function($i): int use (&$mapperWasCalled) {
    $mapperWasCalled = true;
    return $i * $i;
});
// $mapperWasCalled is still false!

filter

你可以将过滤器谓词应用于懒列表,它将“懒”地应用过滤器,这意味着你的过滤器函数不会在真正强制评估列表之前被调用。

$filterFnWasCalled = false;
$oddNumbers = $lazyList->filter(function (int $i): bool use (&$filterFnWasCalled) {
    $filterFnWasCalled = true;
    return ($i % 2 === 1);
});
// $filterFnWasCalled is still false!

迭代

你也可以更传统地迭代懒列表;它是一个迭代器。

foreach ($squares as $square) {
    echo $square . "\n";
}
/* Output:
 * 1
 * 4
 * 9
 * 16
 * 25
 */

它甚至支持索引 => 值迭代

foreach ($squares as $index => $square) {
    echo $index . ": " . $square . "\n";
}
/* Output:
 * 0: 1
 * 1: 4
 * 2: 9
 * 3: 16
 * 4: 25
 */

take($count)

你也可以从开始取一定数量的元素

$l = \Spencerwi\Lazy_list\LazyList::fromArray([1,2,3,4,5]);
$l->take(2); // returns the array [1,2]

// What happens when we take too many?
$l->take(99); // we get the whole list as an array: [1,2,3,4,5]

toArray()

你可以使用 toArray() 将整个列表直接转换为数组

$l = \Spencerwi\Lazy_list\LazyList::fromArray([1,2,3,4,5]);
$->toArray(); // [1,2,3,4,5]

请务必小心使用此方法,因为如果你使用生成器创建一个无限列表(如果生成器永远不会返回 null),则调用 toArray() 将会导致无限循环。不幸的是,没有方法可以预先知道生成器是无限的,否则我们会在尝试将无限 LazyList 转换为 toArray() 时抛出异常。

reduce()

除了 map 之外,你还有它的朋友 reduce,它接受一个初始值和一个在列表上“成对”工作的函数,它调用你提供的函数,首先在初始值和第一个元素上,然后在上一个结果和第二个元素上,然后在 那个 结果和第三个元素上,依此类推。

$l = \Spencerwi\Lazy_list\LazyList::fromArray([2,3,4]);
$sum = $l->reduce(1, function(int $previous, int $current) {
  return $previous + $current;
});
// $sum is now ((1+2)+3)+4, that is, 10. 

如果你尝试“归约”一个空列表,你只会得到“初始”值。这就是为什么需要它。

$l = \Spencerwi\Lazy_list\LazyList::fromArray([]);
$sum = $l->reduce(1, function(int $previous, int $current) {
  return $previous + $current;
});
// $sum is now just 1, since the list was empty

此操作是“急切”的,意味着它评估整个列表。与 toArray() 一样,这意味着如果你有一个无限 LazyList,则 reduce() 将导致无限循环。