benconda/collection

由生成器驱动,支持泛型,易于扩展和不可变的集合库。设计上采用延迟加载且内存友好。接受任何可迭代对象 🔥(生成器、数组、迭代器等)

1.0.0 2024-07-19 15:52 UTC

This package is auto-updated.

Last update: 2024-09-29 08:07:39 UTC


README

由生成器驱动,支持泛型,易于扩展和不可变的集合库。设计上采用延迟加载且内存友好。接受任何可迭代对象 🔥(生成器、数组、迭代器等)

需求

使用此库需要至少php 8.2

用法

首先需要从可迭代对象创建集合,它可以是数组,或任何可迭代对象(生成器、对象迭代器等)

$collection = Collection::from($myIterable);

现在您可以应用一个或多个修改器

use BenConda\Collection\Collection;
// [...]

$collection = Collection::from(range(1, 10))
    ->filter(callback: static fn(int $item): bool => $item > 5)
    ->map(on: fn(int $item): string => "The number is $item");

每次调用修改器方法时,都会返回集合的新实例,不会进行覆盖。

集合是可调用的,因此您也可以这样添加修改器

$collection = Collection::from(range(1, 10))
(
  new Filter(
    callback: fn(int $item): bool => $item >= 5
  )
)
(
  new Map(
    callback: fn(int $item): string => "The number is $item"
  )
);

由于每个修改器都依赖于生成器,因此直到您开始迭代集合,什么都不会执行。

您可以这样获取第一个值

$first = $collection->first(); // $first = The number is 5

请注意,它不会遍历整个数组以返回第一个值,在幕后它只迭代1、2、3、4、5 => 数字是5然后停止。

这是由于生成器的特性,大多数其他集合库都需要遍历整个数组以过滤它,然后再对每个过滤值进行映射,才能获取第一个值。

我们可以直接在集合 $object 上使用 foreach 迭代所有值

$collection = Collection::from(range(1, 10))
foreach ($collection as $key => $item)
{
  // do what you want
}

并且您可以像这样将整个集合转换为一个数组

$collection->toArray();

请注意,按设计我们接受任何作为键,数组将键限制为 int|string 类型,如果键类型不匹配,则将回退到递增的整数键。

修改器

可以使用修改器更改集合的迭代方式,这允许您以内存友好的方式塑造和转换数据。

一些修改器需要一些内存缓冲,并分成另一个名为 BufferedModifier 的命名空间。例如,对于 BenConda\Collection\BufferedModifier\Reverse,为了反转,整个集合需要加载到内存中。

因此请记住,BufferedModifier 命名空间 = 将根据可迭代对象的大小消耗内存。

您可以在此文档中找到修改器列表

注意:文档正在编写中

扩展

添加自定义修改器

只需创建一个实现 BenConda\Collection\Modifier\ModifierInterface 的类

例如,对于重新索引修改器

use Generator;
use BenConda\Collection\Modifier\ModifierInterface;

/**
 * @template TKey
 * @template TValue
 *
 * @implements ModifierInterface<TKey, TValue>
 */
final class Reindex implements ModifierInterface
{
    /**
     *
     * @param iterable<TKey, TValue> $iterable
     *
     * @return Generator<int, TValue>
     */
    public function __invoke(iterable $iterable): Generator
    {
        foreach ($iterable as $value) {
            yield $value;
        }
    }
}

如果您需要一些配置,只需在类中添加一个构造函数。

使用您自己的集合类

有时您需要创建自己的严格类型集合类。

为此,您可以扩展 CoreCollection 类,并仅实现所需的修改器方法。

有时您可能需要一个可变的自定义集合,对于这种情况,您可以扩展 MutableCoreCollection。您可以在此测试中找到一个示例

请注意,即使对于可变集合,您仍然依赖于生成器,因此每次您修改集合时,直到您遍历它,实际上什么都不会执行。