大脚侠/php-iter

一系列函数式迭代器。

0.1.4 2023-08-10 16:53 UTC

This package is not auto-updated.

Last update: 2024-09-21 17:14:44 UTC


README

为PHP提供类似Rust的迭代器。

警告:此包仅是一个概念验证,不应在生产环境中使用。

特性

  • 惰性迭代器;
  • 可链方法;
  • 精心设计、连贯的API。

优点

  • 极大地提高了代码的可读性。

缺点

  • 与经典for循环相比,运行时成本较高(大约慢15倍!)。但对于小循环(小于1000个元素),这种运行时成本可能是可以接受的。

安装

在您的PHP项目中,运行

composer require dajoha/php-iter

基本用法

$numbers = [1, 30, 50, 123, 3, 5, 100, 3780];

$output = iter($numbers)          // Convert the input array to an `IteratorInterface`
    ->filter(fn($n) => $n > 100)  // Keep only numbers which are > 100 
    ->map(fn($n) => "Number $n")  // Map each remaining number to a formatted string
    ->join("\n");                 // Reduce the iterator to a single string

echo "$output\n";

输出

Number 123
Number 3780

更多示例

请参阅此存储库中的/examples目录以获取更多用法示例。

API概述

API提供了一个中心接口:IteratorInterface,它扩展了原生的PHP Iterator,但给它提供了更多的能力。

有两种原生的类实现了IteratorInterface

  • 生成器,可以从任何输入源(如简单数组或任何实现了原生PHP Iterator的任何东西)创建IteratorInterface
  • 修饰器,将给定的IteratorInterface转换成另一个。

一旦创建了迭代器,就必须以某种方式“消费”它,以获得有用的结果(最基本的方式是调用原生PHP方法Iterator::next())。在此文档中,这被称为迭代器的归约。在IteratorInterface中提供了某些方法,以便处理非常常见的归约操作,如转换为数组(toValues())、对数字求和(sum())... 所有这些归约方法都在AbstractIterator中实现,该包中的每个类都基于它。

生成器

生成器是可以从任何类型的输入参数构建的IteratorInterface

例如,一个生成器可以是提供以下内容的类

  • 一个简单的具体值列表,如[78, 'foo', 'bar']
  • 通过提供特定时间段作为输入,获取著名音乐家的列表;
  • 素数无限列表。

修饰器

修饰器是一个IteratorInterface,它接受一个可迭代对象作为第一个输入,并在消费时转换内部可迭代对象的结果。

每个原生修饰器类在IteratorInterface中都有一个专用方法,允许将其与其他修饰器(或与最终的归约方法)链在一起。

例如

  • “映射”修饰器迭代器转换其内部迭代器的每个值。
  • “过滤”修饰器迭代器仅提供满足给定条件的值。

归约器

归约器是方法(通常在AbstractIterator内部实现),通过消费其迭代器的元素(不一定所有元素,尽管通常是这种情况)将给定的迭代器转换为一个最终值。

例如,AbstractIterator::sum()是一个归约方法,它消费迭代器的所有元素(假设它们是数字),并返回这些元素的总和。

原生生成器的摘要

“Iter”生成器

“Iter”类是最基本的生成器:它简单地包装了给定的可迭代对象,它可以是一个

  • PHP数组(通过内部使用ArrayIterator);
  • PHP Iterator
  • 一个php IteratorAggregate(通过尝试获取内部迭代器);
  • 一个php可调用对象(通过将其包装到Func生成器中)。

iter()全局函数

Iter生成器使用非常普遍,因此提供了一个全局函数来包装其构造函数:iter()

其他原生生成器

描述
AsciiChars遍历字符串中的字节
Chain将多个子迭代器链接在一起
Chars遍历字符串中的utf-8字符
Counter生成自定义的数字序列
Forever无限重复一个值
Func永远返回函数调用更新的结果
Letters遍历已知的字符序列
Zip同时遍历多个迭代器
Alternate交替多个迭代器的值
Interleave交错两个迭代器的值

IteratorInterface方法总结

修改器方法

修改器方法是将实际迭代器转换为另一个迭代器的。以下是原生修改器方法列表

chunks()        // Create an iterator over chunks of N elements
filter()        // Filter the values of the iterator by using a callable
filterKeys()    // Filter the keys of the iterator by using a callable
map()           // Map the values of the iterator by using a callable
mapKeys()       // Map the keys of the iterator by using a callable
mapKeyValues()  // Map the keys and values of the iterator by using a callable
skip()          // Skip the given number of elements at the start of the iterator
flatten()       // Flatten the iterator, by assuming that each element is iterable itself
limit()         // Limit the number of elements of the iterator
slice()         // A combination of skip() and limit()
zip()           // Iterate over multiple iterators simultaneously
alternate()     // Alternate values of multiple iterators
interleave()    // Interleaves the values of the iterator with another iterator
loop()          // Loop over the iterator a certain number of times
run()           // Just run the given callable on each item
apply()         // Wrap the iterator into a custom iterator

消耗/减少方法

一旦最终创建了所需的迭代器,则可以调用一个(且仅一个)“减少”方法。以下是减少方法列表

isFound()   // Advance the iterator until the given predicate returns `true`
find()      // Advance the iterator until the given predicate returns `true`
first()     // Return the first value of the iterator
last()      // Return the last value of the iterator. Consume the iterator entirely.
nth()       // Return the given Nth value of the iterator. Consume the iterator until this item is reached
reduce()    // Reduce the iterator to a single value
all()       // Check if all the iterator values fill the requirement of the given predicate
any()       // heck if at least one of the iterator values fills the requirement of the given predicate
count()     // Return the number of items of the iterator. Consume the iterator entirely
min()       // Return the minimum value of the iterator
max()       // Return the minimum value of the iterator
sum()       // Return the sum of the values of the iterator
average()   // Return the average of the values of the iterator
join()      // Join all the values of the iterator into a single string
toValues()  // Return an array of all the values of the iterator
toArray()   // Return an array of all the values of the iterator
consume()   // Consume all the iterator (like toValues(), but don't return anything)

运行测试套件

$ composer create-project dajoha/php-iter
$ cd php-iter
$ vendor/bin/phpunit