loophp/iterators

缺失的PHP迭代器。

支持包维护!
drupol

3.2.1 2024-08-27 16:04 UTC

README

Latest Stable Version GitHub stars Total Downloads GitHub Workflow Status Type Coverage License Donate!

PHP 迭代器

描述

缺失的PHP迭代器。

特性

  • CachingIteratorAggregate
  • ChunkIterableAggregate
  • ClosureIterator: ClosureIterator(callable $callable, array $arguments = [])
  • ClosureIteratorAggregate: ClosureIteratorAggregate(callable $callable, array $arguments = [])
  • ConcatIterableAggregate
  • FilterIterableAggregate
  • InterruptableIterableIteratorAggregate: InterruptableIterableIteratorAggregate(iterable $iterable)
  • IterableIterator: IterableIterator(iterable $iterable)
  • IterableIteratorAggregate: IterableIteratorAggregate(iterable $iterable)
  • MapIterableAggregate
  • MersenneTwisterRNGIteratorAggregate
  • MultipleIterableAggregate
  • PackIterableAggregate
  • PausableIteratorAggregate
  • RandomIterableAggregate
  • ReductionIterableAggregate
  • ResourceIteratorAggregate
  • SimpleCachingIteratorAggregate
  • SortIterableAggregate
  • StringIteratorAggregate
  • TypedIterableAggregate
  • UniqueIterableAggregate
  • UnpackIterableAggregate

安装

composer require loophp/iterators

用法

CachingIteratorAggregate

允许您缓存任何迭代器。然后您可以免费获得可重置的生成器。

此实现的优点是性能。它非常快,无法与其他任何有状态的定制实现相提并论。

使用此迭代器的优点是性能。它非常快,无法与其他任何有状态的定制实现相提并论。

此迭代器将缓存任意类型的关键字和值。

<?php

// Generator
$generator = static function (): \Generator {
    yield true => 'foo';
    yield false => 'bar';
    yield ['foo', 'bar'] => 'foobar';
};

$iterator = new CachingIteratorAggregate($generator());

foreach ($iterator as $key => $value); // This will work.
foreach ($iterator as $key => $value); // This will also work.

ChunkIterableAggregate

<?php

$iterator = (new ChunkIterableAggregate(
    range('a', 'j'),
    2
));

foreach ($iterator as $chunk) {} // ['a', 'b'], ['c', 'd'], ...

FilterIterableAggregate

<?php

$iterator = (new FilterIterableAggregate(
    range(0, 5),
    static fn (int $v, int $key, iterable $iterable): bool =>
        0 === (($v + 2 * $key + count($iterable)) % 2)
));

foreach ($iterator as $filteredValue) {} // 0, 2, 4

InterruptableIterableIteratorAggregate

允许您在任何时候中断迭代器。

当与无限项集合一起使用时很有用。

<?php

// Generator
$naturals = static function () {
    $i = 0;

    while (true) {
        yield $i++;
    }
};

$iterator = new InterruptableIterableIteratorAggregate($generator());

foreach ($iterator as $generator => [$key, $value]) {
    var_dump($value);

    if (10 === $value) {
        $generator->send(InterruptableIterableIteratorAggregate::BREAK);
    }
}

MapIterableAggregate

<?php

$iterator = (new MapIterableAggregate(
    range('a', 'c'),
    static fn (string $letter, int $key, iterable $iterable): string =>
        sprintf(
            '%s::%s::%s',
            $key,
            $letter,
            gettype($iterable)
        )
));

foreach ($iterator as $tranformedValue) {}

MersenneTwisterRNGIteratorAggregate

<?php

$rngGenerator = (new MersenneTwisterRNGIteratorAggregate())
    ->withMin(1)
    ->withMax(10)
    ->withSeed($seed);

foreach ($rngGenerator as $randomValue) {} // Random integers in [1, 10]

PackIterableAggregate

<?php

// Generator
$generator = static function (): \Generator {
    yield true => 'foo';
    yield false => 'bar';
    yield ['foo', 'bar'] => 'foobar';
};

$iterator = new PackIterableAggregate($generator());

foreach ($iterator as $value);
/*
$value will yield the following values:

- [true, 'foo']
- [false, 'bar']
- [['foo', 'bar'], 'foobar']
*/

UniqueIterableAggregate

<?php

$generator = static function(): Generator {
    while (true) {
        yield mt_rand(0, 9);
    }
};

$iterator = new UniqueIterableAggregate($generator(), 1000);

foreach ($iterator as $value) {} // 9 random values only.

UnpackIterableAggregate

<?php

// Generator
$generator = static function (): \Generator {
    yield [true, 'foo'];
    yield [false, 'bar'];
    yield [['foo', 'bar'], 'foobar'];
};

$iterator = new UnpackIterableAggregate($generator());

foreach ($iterator as $key => $value);
/*
$key and $value will yield the following values:

- true => 'foo'
- false => 'bar'
- ['foo', 'bar'] => 'foobar'
*/

ClosureIterator

<?php

$callable = static fn (int $from, int $to) => yield from range($from, $to);

$iterator = new ClosureIterator($callable(10, 20));

IterableIterator

<?php

$iterator = new IterableIterator(range(1, 10));

PausableIteratorAggregate

<?php

$inputIterator = new ArrayIterator(range('a', 'e'));
$iteratorAggregate = new PausableIteratorAggregate($inputIterator);

$i = 0;
foreach ($iteratorAggregate as $v) {
    var_dump($v) // Print: 'a', 'b', 'c'
    if (++$i === 2) {
        break;
    }
}

foreach ($iteratorAggregate->rest() as $v) {
    var_dump($v) // Print: 'd', 'e'
}

RandomIterableAggregate

为了正确使用此迭代器,用户需要提供一个额外的参数 seed。默认情况下,此参数设置为零,因此生成的迭代器将与原始迭代器相同。

通过在零和 seed 的值之间选择一个随机整数来选择随机项。如果该值为零,则迭代器将产生其他值,并从下一个值开始。

seed 越大,熵越大,产生随机项所需的时间越长。然后用户可以选择适当的值。通常,一个好的值是装饰迭代器具有的大约两倍数量。

如果您愿意多次迭代此迭代器,请使用 CachingIteratorAggregate 来缓存结果。

此迭代器在任意类型的关键字和值上工作。

<?php

$seed = random_int(0, 1000);
$inputIterator = new ArrayIterator(range('a', 'e'));
$iterator = new RandomIterableAggregate($inputIterator, $seed);

foreach ($iterator as $v) {
    var_dump($v);
}

$iterator = new CachingIteratorAggregate(
    (new RandomIterableAggregate($inputIterator, $seed))->getIterator()
);

foreach ($iterator as $v) {
    var_dump($v);
}
foreach ($iterator as $v) {
    var_dump($v);
}

ReductionIterableAggregate

<?php

$iterator = (new ReductionIterableAggregate(
    range(0, 10),
    static fn (int $carry, int $value, int $key, iterable $iterable): int => $carry + $value,
    0
));

foreach ($iterator as $reduction) {} // [0, 1, 3, 6, 10, 15, 21, 28, 36, 45, 55]

SortIterableAggregate

实现了一个稳定的排序迭代器聚合

这意味着如果两个元素具有相同的键,则在输入中较早出现的元素也将较早出现在排序输出中。

$valueObjectFactory = static fn (int $id, int $weight): object => new class($id, $weight)
{
    public function __construct(public readonly int $id, public readonly int $weight) {}
};

$input = [
    $valueObjectFactory(id: 1, weight: 1),
    $valueObjectFactory(id: 2, weight: 1),
    $valueObjectFactory(id: 3, weight: 1),
];

$sort = new SortIterableAggregate(
  $input,
  static fn (object $a, object $b): int => $a->weight <=> $b->weight
);

代码质量、测试、基准测试

每当将更改引入库中时,Github 都会运行测试。

该库使用 PHPUnit 编写测试。您可以在 tests 目录中自由检查它们。

在每次提交之前,使用 GrumPHP 执行一些检查;运行 composer grumphp 以手动检查。

静态分析器也在控制代码。PHPStan和PSalm已经启用到最大级别。

贡献

请随时通过发送拉取请求进行贡献。我们是一个通常非常响应迅速的团队,我们将从开始到结束帮助你处理你的拉取请求。

由于某些原因,如果你不能为代码做出贡献但愿意帮助,赞助是一个好、可靠和安全的方式来表达对我们投入在这个包上的时间的感激之情。

Github上赞助我,或赞助任何贡献者

变更日志

查看CHANGELOG.md以获取基于git提交的变更日志。

如需更详细的变更日志,请查看发布变更日志