worksolutions/php-collections

1.1.7 2022-10-20 14:44 UTC

README

Tests Code Coverage Scrutinizer Code Quality Latest Stable Version

PHP 的集合库。它通过函数式方法方便地处理常见的数据结构。主要数据结构包括:列表、映射、栈、队列、集合。库的一部分是流 API。它提供了一种更函数式的迭代和处理元素的方法。

其他语言版本: 俄语

要求

PHP 7.1+

安装

composer require worksolutions/php-collections

示例

<?php
use WS\Utils\Collections\CollectionFactory;
use WS\Utils\Collections\Functions\Predicates;

// Getting filtered elements
CollectionFactory::from([1, 2, 3])
    ->stream()
    ->filter(Predicates::greaterThan(1))
    ->getCollection(); // Collection [2, 3]

// Print directory files
CollectionFactory::fromIterable(new DirectoryIterator(__DIR__))
    ->stream()
    ->each(static function (SplFileInfo $fileInfo) {
        echo $fileInfo->getFilename() . "\n";
    });

基本概念

该库基于一致的数据处理和转换方法。创建一种转换管道,可以按顺序执行某些步骤。每个步骤只负责自己的一小部分工作。在这种情况下,步骤可以重用,因为它们是原子的。

本质上,该库由几个部分组成,包括

  • 数据结构。 每个结构都有其独特的特性,通过接口及其描述和实现来体现。在这种情况下,数据结构的实现可以不同。
  • 集合工厂。 集合工厂提供了许多静态方法,用于方便地创建集合。
  • 集合流。 流遍历和转换集合,每个转换都会创建一个新的集合实例。
  • 遍历和转换函数。 函数集包含在遍历期间易于使用的预准备函数构造器。通过它们的示例,您可以创建和使用更符合您领域特定需求的函数。

数据结构

该库基于最流行的数据结构,可以在不使用任何额外库和类的情况下独立使用。库的所有其他部分都依赖于这些结构,特别是 Collection 接口。所有集合数据结构都包含许多元素,您可以使用它们执行基本操作,如:遍历、转换、聚合等。

集合

[↑ 数据结构]

集合 - 集合的主要基础接口。除映射(Map)之外的所有数据结构都实现此接口,所有附加功能(工厂、遍历线程)都使用此接口。为了在您的应用程序中保持通用性,建议使用 Collection 接口,但前提是不违反使用结构的初衷。

集合可以使用 foreach 循环进行遍历。

接口方法

add - 向集合中添加一个项目

[↑ 集合]

add($element: mixed): bool;

将项目添加到集合的末尾。成功返回true,失败返回false

use WS\Utils\Collections\CollectionFactory;

$collection = CollectionFactory::from([1, 2]); // [1, 2]
$collection->add(10); // [1, 2] -> [1, 2, 10];

addAll - 向集合中添加多个项目

[↑ 集合]

addAll($elements: iterable): bool;

将多个项目添加到集合的末尾。成功返回true,失败返回false

use WS\Utils\Collections\CollectionFactory;

$collection = CollectionFactory::from([1, 2]); // [1, 2]
$collection->add([10, 11, 12]); // true
$collection->toArray(); // [1, 2] -> [1, 2, 10, 11, 12];

merge - 合并集合

[↑ 集合]

merge($collection: Collection): bool;

该方法将当前集合与传入的集合合并。成功返回true,失败返回false

use WS\Utils\Collections\CollectionFactory;

$collection = CollectionFactory::from([1, 2]); // [1, 2]
$mergingCollection = CollectionFactory::from([11, 12]); // [11, 12]
$collection->merge($mergingCollection); // true
$collection->toArray(); // [1, 2, 10, 11, 12];

clear - 移除集合中的所有元素

[↑ 集合]

clear(): void;

该方法移除集合中的所有元素。

use WS\Utils\Collections\CollectionFactory;

$collection = CollectionFactory::from([1, 2]); // [1, 2]
$collection->clear(); // null
$collection->toArray(); // [];

remove - 移除集合中的项目

[↑ 集合]

remove($element: mixed): bool;

移除集合中的特定项目。该方法返回删除元素的标志。如果元素不存在,则返回false

use WS\Utils\Collections\CollectionFactory;

$collection = CollectionFactory::from([1, 2, 3]); // [1, 2, 3]
$collection->remove(2); // true
$collection->remove(4); // false
$collection->toArray(); // [1, 3];

contains - 检查集合中是否存在元素

[↑ 集合]

contains($element: mixed): bool;

检查特定项目是否存在于集合中。如果元素不存在,则返回false

use WS\Utils\Collections\CollectionFactory;

$collection = CollectionFactory::from([1, 2, 3]); // [1, 2, 3]
$collection->contains(2); // true
$collection->contains(4); // false

equals - 比较两个集合是否相等

[↑ 集合]

equals($collection: Collection): bool;

该方法检查传入的集合是否与当前集合相等,这意味着一个集合的所有元素都包含在另一个集合中,且元素数量相等。如果集合不相等,则返回false

use WS\Utils\Collections\HashSet;

$set1 = new HashSet([1, 2, 3]);
$set2 = new HashSet([3, 2, 1]);
$set3 = new HashSet([3, 2]);

$set1->equals($set2); // true
$set2->equals($set1); // true
$set1->equals($set3); // false

size - 获取集合中的项目数量

[↑ 集合]

size(): int;

该方法返回集合中的元素数量。如果集合为空 - 0。

use WS\Utils\Collections\CollectionFactory;

$collection = CollectionFactory::from([1, 2, 3]); // [1, 2, 3]
$collection->size(); // 3

$emptyCollection = CollectionFactory::from([]);
$emptyCollection->size(); // false

isEmpty - 检查集合是否为空

[↑ 集合]

isEmpty(): bool;

该方法返回空集合的属性。如果集合中有元素,则返回false

use WS\Utils\Collections\CollectionFactory;

$collection = CollectionFactory::from([1, 2, 3]); // [1, 2, 3]
$collection->isEmpty(); // false

$emptyCollection = CollectionFactory::from([]);
$emptyCollection->isEmpty(); // true

toArray - 将集合元素转换为数组

[↑ 集合]

toArray(): array;

一个由集合元素组成的索引数组方法,元素的顺序取决于内部表示。

use WS\Utils\Collections\CollectionFactory;

$collection = CollectionFactory::from([1, 2, 3]); // [1, 2, 3]
$collection->toArray(); // [1, 2, 3]

$emptyCollection = CollectionFactory::from([]);
$emptyCollection->toArray(); // []

copy - 获取集合的副本

[↑ 集合]

copy(): Collection;

该方法返回集合的精确副本。集合是可变的。这意味着使用修改方法会修改集合;为确保集合不可变,建议使用副本方法。

use WS\Utils\Collections\CollectionFactory;

$collection = CollectionFactory::from([1, 2, 3]); // [1, 2, 3]
$copyOfCollection = $collection->copy(); // Collection

$copyOfCollection === $collection; // false

stream - 获取集合遍历流(Stream)

[↑ 集合]

stream(): Stream;

一个实现集合遍历接口的对象(Stream)。集合遍历流是一个非常强大的工具,在大多数情况下您在开发过程中都需要处理它。[更多...](#Collection streams)

use WS\Utils\Collections\CollectionFactory;

$collection = CollectionFactory::from([1, 2, 3]); // [1, 2, 3]
$collection
    ->stream()
    ->each(static function (int $el) {var_export($el);}); // 1 2 3

使用foreach循环遍历集合

[↑ 集合]

集合可以在 * foreach * 循环中进行遍历。集合的迭代顺序取决于特定类的内部实现。

use WS\Utils\Collections\CollectionFactory;

$collection = CollectionFactory::from([1, 2, 3]); // [1, 2, 3]

foreach($collection as $item) {
    var_export($item);
}

列表(ListSequence)

[↑ 数据结构]

列表是一种数据结构,其中元素的顺序是严格定义的。具有相同元素集合但顺序不同的列表不相等。ListSequence接口扩展了Collection接口。

ListSequence接口扩展接口: Collection

实现ListSequence接口的类:ArrayList, ImmutableList

接口方法

get - 通过序号获取项目

[↑ 列表 (ListSequence)]

get($index: int): mixed;

该方法返回索引处的项目。如果索引处不存在元素,则返回null。列表的第一个元素索引为0。

use WS\Utils\Collections\ArrayList;

$list = ArrayList::of(1, 2);

$list->get(0); // 1
$list->get(1); // 2
$list->get(2); // null

set - 替换列表项目

[↑ 列表 (ListSequence)]

set($element: mixed, $index: int): mixed;

该方法通过索引替换元素。返回被当前方法替换的元素的值。如果尝试替换一个不存在的元素,将抛出 OutOfRangeException。

use WS\Utils\Collections\ArrayList;

$list = ArrayList::of(1, 2);

$list->set(3, 0); // 1
$list->set(4, 1); // 2
$list->set(4, 2); // OutOfRangeException

indexOf - 获取元素的序号索引

[↑ 列表 (ListSequence)]

indexOf($element: mixed): ?int;

该方法返回找到的元素的第一索引。如果列表中没有值,它将返回 null

use WS\Utils\Collections\ArrayList;

$list = ArrayList::of(1, 2, 1, 3);

$list->indexOf(1); // 0
$list->indexOf(2); // 1
$list->indexOf(4); // null

lastIndexOf - 获取最后一个匹配项的序号索引

[↑ 列表 (ListSequence)]

lastIndexOf($element: mixed): ?int;

该方法返回找到的元素的最后索引。如果列表中没有值,它将返回 null

use WS\Utils\Collections\ArrayList;

$list = ArrayList::of(1, 2, 1, 3);

$list->indexOf(1); // 2
$list->indexOf(2); // 1
$list->indexOf(3); // null

removeAt - 通过索引删除元素

[↑ 列表 (ListSequence)]

removeAt(int $index): mixed;

该方法通过索引删除元素,删除索引后的元素向起始方向移动一个位置。返回被删除项的值。如果索引不存在,它将返回 null

use WS\Utils\Collections\ArrayList;

$list = ArrayList::of(1, 2, 1, 3);

$list->removeAt(1); // 2
$list->toArray(); // [1, 1, 3]

集合

[↑ 数据结构]

该集合只包含唯一元素,元素的顺序可以是任意的。也就是说,使用 add 方法添加元素并不保证它在迭代期间在其他元素中的最后位置,并且如果存在具有相同值的元素,后者将不会被添加到集合中。

唯一性由值确定,对于对象,则由特定对象的唯一性确定,或者,如果对象实现了 HashCodeAware 接口,则由调用 getHashCode (): string; 返回的结果的唯一性确定。

Set 接口扩展了基接口: Collection

实现 Set 接口的类: HashSet

队列

[↑ 数据结构]

类似于队列的数据结构方便于按到达顺序对数据进行顺序处理。它提供了方便的添加和消费项的方法。首先进入队列的第一个元素将是第一个离开的元素。

Queue 接口扩展了基接口: Collection

实现 Queue 接口的类: ArrayQueue

接口方法

offer - 将项目插入到队列中

[↑ 队列]

offer($element): bool;

该方法将项目添加到队列的末尾。如果没有添加项目,则返回 false,可能是在有限队列的情况下。

use WS\Utils\Collections\ArrayQueue;

$queue = ArrayQueue::of(1, 2);

$queue->offer(3); // [1, 2, 3]
$queue->peek(); // 3

poll - 从队列中获取项目并删除它

[↑ 队列]

poll(): mixed;

该方法返回一个元素并从队列的头部删除它。如果没有项目在队列中,将抛出 RuntimeException

use WS\Utils\Collections\ArrayQueue;

$queue = ArrayQueue::of(1, 2);

$queue->peek(); // 2
$queue->poll(); // [1]
$queue->peek(); // 1

peek - 获取项目而不从队列中删除它

[↑ 队列]

poll(): mixed;

该方法返回一个元素。在这种情况下,队列不会改变,元素保持在原位。如果没有项目在队列中,将抛出 RuntimeException

use WS\Utils\Collections\ArrayQueue;

$queue = ArrayQueue::of(1, 2, 3);

$queue->peek(); // 2
$queue->size(); // 3

[↑ 数据结构]

栈是一种数据结构,其逻辑与队列的逻辑相反。栈顶的第一个项目将是第一个进入的,也将被弹出。

Stack 接口扩展了基接口: Collection

实现 Stack 接口的类: ArrayStack

接口方法

push - 推入项目

[↑ 栈]

push($element: mixed): bool;

该方法将项目推送到栈顶。如果没有添加元素,则返回 false,可能是在受限的情况下。

use WS\Utils\Collections\ArrayStack;

$queue = ArrayStack::of(1, 2);

$queue->push(3); // [1, 2, 3]
$queue->peek(); // 3

pop - 取出最后添加的项目

[↑ 栈]

pop(): mixed;

该方法从栈顶返回项目。栈顶是先于接收到的项目添加的元素。如果没有元素在栈上,将抛出 RuntimeException

use WS\Utils\Collections\ArrayStack;

$queue = ArrayStack::of(1, 2, 3); // [1, 2, 3]

$queue->pop(); // 3
$queue->pop(); // 2
$queue->push(4); // [1, 4]
$queue->pop(); // 4
$queue->peek(); // 1

peek - 获取最后添加的项目而不修改栈

[↑ 栈]

peek(): mixed;

该方法返回栈顶的项。如果没有元素在栈中,将抛出 RuntimeException 异常。

use WS\Utils\Collections\ArrayStack;

$queue = ArrayStack::of(1, 2, 3); // [1, 2, 3]

$queue->pop(); // 3
$queue->peek(); // 3
$queue->peek(); // 3

$queue->pop(); // 2
$queue->pop(); // 1
$queue->peek(); // RuntimeException

映射

[↑ 数据结构]

Map 接口表示一种映射,换句话说是一个字典,其中每个元素代表一个键值对。Map 键在值上是唯一的,如果它们是对象,则通过对象的引用唯一性或通过实现 HashCodeAware 接口并调用 getHashCode (): string; 方法的结果唯一性来达到。

Map 接口扩展了基本接口: IteratorAggregate

实现 Stack 接口的类:HashMap

接口方法

put - 添加键值对

[↑ Map]

put($key: mixed, $value: mixed): bool;

该方法向结构对象添加键/值对。如果没有添加项,则返回 false,可能是由于限制。键和值可以是标量类型、数组或对象的数据。

use WS\Utils\Collections\HashMap;

$map = new HashMap();
$map->put('one', 1);
$map->put('two', 2);

foreach ($map as $k => $v) {
    var_dump($k); // one | two
    var_dump($v); // 1   | 2
}

get - 通过键获取对的值

[↑ Map]

get($key): mixed;

该方法通过键 key 返回对的值。如果没有值,它将返回 null

use WS\Utils\Collections\HashMap;

$map = new HashMap();
$map->put('one', 1);
$map->put('two', 2);

$map->get('one'); // 1
$map->get('three'); // null

keys - 获取地图键的集合

[↑ Map]

keys(): Collection<mixed>;

该方法返回一个包含所有地图键的集合。

use WS\Utils\Collections\HashMap;

$map = new HashMap();
$map->put('one', 1);
$map->put('two', 2);

foreach ($map->keys() as $k) {
    var_dump($k); // one | two
}

values - 获取地图值的集合

[↑ Map]

values(): Collection<mixed>;

该方法返回一个包含所有地图对值的集合。

use WS\Utils\Collections\HashMap;

$map = new HashMap();
$map->put('one', 1);
$map->put('two', 2);

foreach ($map->keys() as $v) {
    var_dump($v); // 1 | 2
}

remove - 通过键删除对

[↑ Map]

remove($key: mixed): bool;

该方法通过键 key 从地图中删除一个对。

use WS\Utils\Collections\HashMap;

$map = new HashMap();
$map->put('one', 1);
$map->put('two', 2);

$map->remove('one');
foreach ($map->keys() as $v) {
    var_dump($v); // 2
}

containsKey - 标记键对的存在

[↑ Map]

containsKey($key: mixed): bool;

该方法返回一个表示存在具有键 key 的对的指示。

use WS\Utils\Collections\HashMap;

$map = new HashMap();
$map->put('one', 1);
$map->put('two', 2);

$map->containsKey('one'); // true

containsValue - 标记通过值对的存在

[↑ Map]

containsValue($value: mixed): bool;

该方法返回一个表示存在具有值 value 的对的指示。

use WS\Utils\Collections\HashMap;

$map = new HashMap();
$map->put('one', 1);
$map->put('two', 2);

$map->containsValue(1); // true
$map->containsValue(3); // false

size - 卡片中对的数目

[↑ Map]

size(): int;

该方法返回对的数目。

use WS\Utils\Collections\HashMap;

$map = new HashMap();
$map->put('one', 1);
$map->put('two', 2);

$map->size(); // 2

$emptyMap = new HashMap();
$map->size(); // 0

stream - 获取带有键值对对的遍历流(Stream)

[↑ Map]

stream(): Stream;

方法返回 Stream 接口的对象。内部集合元素是键/值对。

use \WS\Utils\Collections\HashMap;
use \WS\Utils\Collections\MapEntry;

$map = new HashMap();

$map->put('one', 1);
$map->put('two', 2);
$map->put('tree', 3);

$map->stream()->each(static function (MapEntry $mapEntry) {
    var_export($mapEntry->getKey()); // 'one', 'two', 'three'
    var_export($mapEntry->getKey()); // 1    , 2    , 3
});

foreach 循环中遍历地图

[↑ Map]

Map 接口的对象可以在 foreach 循环中迭代。在这种情况下,键和值将按顺序传递。键可以是任何类型,但不能是数组。

use \WS\Utils\Collections\HashMap;

$map = new HashMap();

$map->put(new SplObjectStorage(), 1);
$map->put(null, 2);
$map->put(false, 3);
$map->put(true, 4);
$map->put(0, 5);

foreach($map as $key => $value) {
    var_export($key);   // object of SplObjectStorage class| null| false| true| 0 
    var_export($value); // 1                               | 2   | 3    | 4   | 5
}

集合工厂

[↑ Up]

CollectionFactory 工厂允许您在不使用特定实现构造函数的情况下创建集合对象,或者也有其他方便的方法来创建集合对象。目前,库的主要结构是 ArrayList,该工厂通过静态方法生成。

示例

use WS\Utils\Collections\CollectionFactory;
use WS\Utils\Collections\Functions\Consumers;

CollectionFactory::numbers(10)
    ->stream()
    ->each(Consumers::dump()); // dumps int(0), int(1), ...

集合创建工厂方法

CollectionFactory::from - 从元素数组生成集合

[↑ Collection factory]

from($values: array): Collection

该方法创建一个由传入数组元素组成的集合。

目前,集合实现是 ArrayList,未来具体实现可能会改变,调用此方法时,应仅依赖于 Collection 接口。

use WS\Utils\Collections\CollectionFactory;
use WS\Utils\Collections\Functions\Consumers;

CollectionFactory::from([1 ,2, 3])
    ->stream()
    ->each(Consumers::dump()); // dumps int(1), int(2), int(3)

CollectionFactory::fromIterable - 使用任何可迭代对象生成集合

[↑ Collection factory]

fromIterable($iterable: iterable): Collection

该方法创建一个集合,其元素由传递的迭代器的元素组成。

目前,集合实现是 ArrayList,未来具体实现可能会改变,调用此方法时,应仅依赖于 Collection 接口。

use WS\Utils\Collections\CollectionFactory;
use WS\Utils\Collections\Functions\Consumers;
use WS\Utils\Collections\Functions\Converters;

CollectionFactory::fromIterable(new DirectoryIterator(__DIR__))
    ->stream()
    ->map(Converters::toPropertyValue('filename'))
    ->each(Consumers::dump()); // Dumps strings with filenames

_CollectionFactory::numbers - 生成整数序列集合

[↑ Collection factory]

numbers($from: int, $to: ?int): Collection

该方法创建一个集合,其元素由整数序列 [$ from .. $ to] 组成。如果未传递 $ to 参数,将返回 [0 .. $ from] 集合。

目前,集合的实现是 ArrayList,将来具体实现可能会更改,在调用此方法时,应仅依赖于 Collection 接口。

use WS\Utils\Collections\CollectionFactory;
use WS\Utils\Collections\Functions\Consumers;

CollectionFactory::numbers(10, 15)
    ->stream()
    ->each(Consumers::dump()); // Dumps  [10, 11, 12, 13, 14, 15]

CollectionFactory::generate - 使用生成器生成集合

[↑ Collection factory]

generate($times: int, $generator: ?callable): Collection

该方法创建一个大小为 $ times 的集合,其元素由调用生成器 $ generator 的结果值组成。

目前,集合的实现是 ArrayList,将来具体实现可能会更改,在调用此方法时,应仅依赖于 Collection 接口。如果您需要一个特定类型的集合实例,您需要使用实现构造函数或它们的静态方法。

use WS\Utils\Collections\CollectionFactory;
use WS\Utils\Collections\Functions\Consumers;

CollectionFactory::generate(3, static function () {
        return random_int(0, 10);
    })
    ->stream()
    ->each(Consumers::dump()); // Dumps for example [9, 7, 2]

MapFactory::fromIterable - 从任何迭代值生成映射

[↑ Collection factory]

MapFactory::fromIterable($iterable: iterable): Map

方法从任何迭代对象创建映射对象。

use WS\Utils\Collections\MapFactory;

MapFactory::fromIterable(['a' => 1, 'b' => 2])
    ->keys() // ['a', 'b']
;

MapFactory::assoc - 从关联数组生成映射

[↑ Collection factory]

MapFactory::assoc(array $assocArray): Map

方法从关联数组创建映射对象。

use WS\Utils\Collections\MapFactory;

MapFactory::assoc(['a' => 1, 'b' => 2])
    ->keys() // ['a', 'b']
;

集合流

[↑ Up]

为了更方便地遍历和转换集合,必须使用流。基本上,所有计算都应通过流完成。要获取流,需要调用集合方法 Collection::stream ()

通过执行函数处理集合,这些函数的接口必须与遍历/转换目的相匹配。有六个接口

  • 断言。用于过滤元素 filter,如果对该元素的断言调用返回布尔正值,则元素保留在流集合中。库中已经包含了一些准备好的断言
  • 转换器。此类函数用于转换 map 流集合。转换器必须返回一个值,该值通过某些属性与集合的传递元素相对应。库中已经包含了一些 准备好的转换器
  • 消费者。消费者函数不修改流集合,但用于遍历 each 集合。将为集合的每个元素调用传递的函数;函数的结果不予考虑。库中已经包含了一些 准备好的消费者
  • 比较器。比较器参与排序项目以确定两个值的排序顺序。如果第一个参数分别小于、等于或大于第二个参数,则必须返回一个小于、等于或大于零的整数。php.net usort。库中已经包含了一些 准备好的比较函数
  • 重组器。转换函数将一个集合转换成另一个 reorganize 而不改变流对象。转换在需要根据原始集合中的所有信息获取最终集合,而不仅仅是将一个元素转换成另一个元素时是必要的。例如,随机排列元素或形成块的方法。库中已经包含了一些 准备好的重组器
  • 收集器。使用 collect 方法将数据收集功能应用于流,实际上,执行此组函数的结果将是执行流的结果。collect 方法是终端的,即调用此方法将终止流。

所有流都属于 Stream 接口,这意味着接口的描述保证了其正确执行,无论具体实现如何,异常只是流行为的特殊情况(when)。

Stream 保证在每个修改方法之后,getCollection 方法将返回不同的对象实例,这是一种从安全角度维护转换期间不可变性的安全方法。

Stream 接口方法

each - 遍历集合元素

[↑ 流]

each($consumer: <fn($element: mixed, $index: int): void>): Stream;

该方法将消费者函数应用于流集合中的每个元素。函数的结果不考虑。调用 each 方法不会改变流中的集合,但同时也访问集合中的每个项目。

use WS\Utils\Collections\CollectionFactory;
use WS\Utils\Collections\Functions\Consumers;

CollectionFactory::numbers(10)
    ->stream()
    ->each(Consumers::dump()) // dumps each element
    ->each(static function ($el) { // prints strings 0, 1, 2, 3
        echo $el."\n"; 
    })
;

walk - 有限遍历集合元素

[↑ 流]

walk($consumer: <fn($element: mixed, $index: int): false|void>, $limit: ?int): Stream;

该方法将消费者函数应用于流集合中的每个元素,就像在 each 方法中一样。函数的结果不考虑。调用 each 方法不会改变流中的集合,但同时也访问集合中的每个项目。

use WS\Utils\Collections\CollectionFactory;
use WS\Utils\Collections\Functions\Consumers;

CollectionFactory::numbers(10)
    ->stream()
    ->walk(Consumers::dump(), 5) // dumps only first 5 elements: 0, 1, 2, 3, 4
    ->walk(static function ($el) { // prints strings 0, 1, 2, 3. Method will be called only 5 times
        if ($el === 4) {
            return false;
        }
        echo $el."\n";
    })
;

filter - 过滤集合元素

[↑ 流]

filter($predicate: <fn($element: mixed): bool>): Stream;

该方法将谓词函数应用于流集合中的每个元素。如果从元素到谓词的调用返回负结果(false, 0, '', []),则该元素将被排除在集合之外。

use WS\Utils\Collections\CollectionFactory;

CollectionFactory::numbers(10)
    ->stream()
    ->filter(static function (int $el): bool {
        return $el % 2 === 0;
    })
    ->getCollection() // returns only first 5 elements: 0, 2, 4, 6, 8
;

map - 转换流集合元素

[↑ 流]

map($converter: <fn($element: mixed): mixed>): Stream;

该方法将流应用于集合中的每个元素,并用函数执行的结果替换传递给集合的元素。

use WS\Utils\Collections\CollectionFactory;

CollectionFactory::numbers(10)
    ->stream()
    ->map(static function (int $el): int {
        return $el * 10;
    })
    ->getCollection() // returns 0, 10, 20, 30, 40, 50, 60, 70, 80, 90
;

reorganize - 流集合转换

[↑ 流]

reorganize($reorganizer: <fn($collection: Collection): Collection>): Stream;

该方法将 $reorganizer 应用于内部集合,然后用方法调用的结果替换内部集合。当需要进行基于完整集合数据的转换时需要。

use WS\Utils\Collections\ArrayStack;
use WS\Utils\Collections\Collection;
use WS\Utils\Collections\CollectionFactory;

CollectionFactory::numbers(10)
    ->stream()
    // reverse collection 
    ->reorganize(static function (Collection $collection): Collection {
        $stack = new ArrayStack();
        foreach ($collection as $item) {
            $stack->push($item);
        }
        $reversed = CollectionFactory::empty();
        while (!$stack->isEmpty()) {
            $reversed->add($stack->pop());
        }
        return $reversed;
    })
    ->getCollection()
;

collect - 收集数据

[↑ 流]

collect($collector: <fn ($collection: Collection): mixed>): mixed;

该方法将收集器函数应用于内部集合并返回结果。当需要使用流对集合执行最终操作时需要。终端方法。

use WS\Utils\Collections\Collection;
use WS\Utils\Collections\CollectionFactory;

$sumOfElements = CollectionFactory::numbers(10)
    ->stream()
    // get sum of collection elements
    ->collect(static function (Collection $collection): int {
        $res = 0;
        foreach ($collection as $item) {
            $res += $item;
        }
        return $res;
    })
;

sort - 对集合中的项目进行排序

[↑ 流]

sort($comparator: <fn($a: mixed, $b: mixed): int>): Stream;

该方法根据$comparator的工作对项目进行排序。比较器确定两个值的排序顺序。如果第一个参数分别小于、等于或大于第二个参数,必须返回一个小于、等于或大于零的整数。php.net usort

use WS\Utils\Collections\CollectionFactory;

$sortedCollection = CollectionFactory::generate(10, static function (): int {
        return random_int(0, 100);
    })
    ->stream()
    // get sorted collection
    ->sort(static function (int $a, int $b): int {
        return $a <=> $b;
    })
    ->getCollection()
;

sortDesc - 以相反顺序对集合中的元素进行排序

[↑ 流]

sortDesc($comparator: <fn($a: mixed, $b: mixed): int>): Stream;

该方法根据$ comparator的工作对元素进行排序,但与常规排序函数不同,元素将以降序排列。编译器确定两个值的排序顺序。如果第一个参数分别小于、等于或大于第二个参数,必须返回一个小于、等于或大于零的整数。php.net usort

use WS\Utils\Collections\CollectionFactory;

$sortedDescendentCollection = CollectionFactory::generate(10, static function (): int {
        return random_int(0, 100);
    })
    ->stream()
    // get sorted collection in the reverse order
    ->sortDesc(static function (int $a, int $b): int {
        return $a <=> $b;
    })
    ->getCollection()
;

sortBy - 按值对集合项目进行排序

[↑ 流]

sortBy($extractor: <fn($el: mixed): scalar>): Stream;

该方法根据每个元素的接收到的$ extractor函数的值对元素进行排序。函数必须返回一个标量值,以启用独立优化排序。按值降序排序的方法sortByDesc类似。

use WS\Utils\Collections\CollectionFactory;

class Container {
    private $value;

    public function __construct($value) {
        $this->value = $value;
    }
    
    public function getValue() {
        return $this->value;
    }
}

$sortedCollection = CollectionFactory::generate(10, static function (): Container {
        return new Container(random_int(0, 100));
    })
    ->stream()
    // get sorted collection
    ->sortBy(static function (Container $container): int {
        return $container->getValue();
    })
    ->getCollection()
;

reduce - 将集合缩减为单个值

[↑ 流]

reduce($accumulator: <fn($el: mixed, $carry: mixed): mixed>): mixed;

该方法将集合转换为单个值。函数接收可迭代元素的值$el和调用同一函数的先前元素的返回结果 $carry。在第一次迭代中,$carry === null。终端方法。

use WS\Utils\Collections\CollectionFactory;

$sumOfCollection = CollectionFactory::numbers(10)
    ->stream()
    // get sum of collection elements
    ->reduce(static function (int $el, ?int $carry = null): int {
        return $carry + $el;
    })
;

when - 通过条件约束流修改

[↑ 流]

when($condition: bool): Stream;

如果$condition不满足,则限制修改,并且所有修改和绕过方法都不会被调用。相反的方法是[always](#移除流修改约束)。

锁定方法

use WS\Utils\Collections\Collection;
use WS\Utils\Collections\CollectionFactory;

$randomElementSizeCollection = CollectionFactory::numbers(random_int(0, 20));

$onlyTenElements = $randomElementSizeCollection
    ->stream()
    // get collection elements only 10 items
    ->when($randomElementSizeCollection->size() > 10)
    ->limit(10)
    ->when($randomElementSizeCollection->size() < 10)
    ->reorganize(static function (Collection $collection) {
        for ($i = $collection->size(); $i < 10; $i++ ) {
            $collection->add($i);
        }
        return $collection;
    })
;

always - 移除流修改约束

[↑ 流]

always(): Stream;

如果流之前通过[when条件](#通过条件约束流修改)阻止了修改,则always方法取消对修改方法进一步调用的限制。

use WS\Utils\Collections\CollectionFactory;

$collection = CollectionFactory::numbers(20);

$onlyTenElements = $collection
    ->stream()
    // get collection elements only 10 items
    ->when($collection->size() > 5)
    ->limit(5)
    ->always()
    ->map(static function (int $el): int {
        return $el * 10;
    })
    ->getCollection() // [0, 10, 20, 30, 40]
;

getCollection - 获取流集合

[↑ 流]

getCollection(): Collection;

该方法根据之前执行的操作返回集合。即使对流调用转换方法,结果集合也将保持不变。终端方法。

use WS\Utils\Collections\CollectionFactory;

$stream = CollectionFactory::numbers(10)
    ->stream();

$collection1 = $stream
    ->map(static function (int $el): int{
        return $el * 10;
    })
    ->getCollection()
;

$collection2 = $stream
    ->filter(static function (int $el): bool {
        return $el > 50;
    })
    ->getCollection()
;

$collection1->size() === $collection2->size(); // false

$collection2->toArray(); // [60, 70, 80, 90]

allMatch - 通过谓词对所有元素进行完整匹配

[↑ 流]

allMatch($predicate: <fn($el: mixed): bool>): bool;

如果对集合的元素调用 $predicate的所有调用都为真(true),则方法将返回true。终端方法。

use WS\Utils\Collections\CollectionFactory;

CollectionFactory::numbers(10)
    ->stream()
    ->allMatch(static function (int $el): bool {
        return $el >= 1;
    }) // false, 0 is less than 1
;

anyMatch- 通过谓词对所有元素进行部分匹配

[↑ 流]

anyMatch(callable $predicate): bool;

如果对集合的元素进行至少一次调用 $ predicate为真(true),则方法将返回true。终端方法。

use WS\Utils\Collections\CollectionFactory;

CollectionFactory::numbers(10)
    ->stream()
    ->anyMatch(static function (int $el): bool {
        return $el > 0;
    }) // true, [1, 2, 3, 4, 5, 6, 7, 8, 9] are grate than 0
;

findAny - 获取任意集合项目

[↑ 流]

findAny(): mixed;

该方法返回集合的任意元素,如果集合为空,则返回null。不保证项是随机选择的。终端方法。

use WS\Utils\Collections\CollectionFactory;

CollectionFactory::numbers(10)
    ->stream()
    ->findAny() // for example - 5
;

findFirst- 获取集合中的第一个项目

[↑ 流]

findFirst(): mixed;

该方法将返回集合的第一个元素,如果集合为空,则返回null。终端方法。

use WS\Utils\Collections\CollectionFactory;

CollectionFactory::numbers(10) // [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] 
    ->stream()
    ->findFirst() // 0
;

findLast- 获取集合中的最后一个项目

[↑ 流]

findLast(): mixed;

该方法将返回集合的最后一个元素,如果集合为空,则返回null。终端方法。

use WS\Utils\Collections\CollectionFactory;

CollectionFactory::numbers(10) // [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] 
    ->stream()
    ->findLast() // 9
;

min - 获取集合的最小元素

[↑ 流]

min($comparator: <fn($a: mixed, $b: mixed): int>): mixed;

该方法将返回比较函数比较下的集合中最小的项,如果集合为空,则返回null。终端方法。

use WS\Utils\Collections\CollectionFactory;
use WS\Utils\Collections\Functions\Reorganizers;

CollectionFactory::numbers(10) // [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] 
    ->stream()
    ->reorganize(Reorganizers::shuffle())
    ->min(static function (int $a, int $b): int {
        return $a <=> $b;
    }) // 0
;

max - 获取集合中的最大项目

[↑ 流]

max($comparator: <fn($a: mixed, $b: mixed): int>): mixed;

该方法将返回比较函数比较下的集合中最大的项,如果集合为空,则返回null。终端方法。

use WS\Utils\Collections\CollectionFactory;
use WS\Utils\Collections\Functions\Reorganizers;

CollectionFactory::numbers(10) // [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] 
    ->stream()
    ->reorganize(Reorganizers::shuffle())
    ->max(static function (int $a, int $b): int {
        return $a <=> $b;
    }) // 9
;

reverse - 反转集合的元素

[↑ 流]

reverse(): Stream;

该方法将元素的顺序转换为反转序列。

use WS\Utils\Collections\CollectionFactory;

CollectionFactory::numbers(10) // [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] 
    ->stream()
    ->reverse()
    ->getCollection() // [9, 8, 7, 6, 5, 4, 3, 2, 1, 0]
;

limit - 将集合缩小到指定大小

[↑ 流]

limit(int $size): Stream;

此方法将元素数量减少到指定大小。如果元素数量已经小于在 $size 限制中指定的数量,元素数量将保持不变。

use WS\Utils\Collections\CollectionFactory;

CollectionFactory::numbers(10) // [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] 
    ->stream()
    ->reverse()
    ->getCollection() // [9, 8, 7, 6, 5, 4, 3, 2, 1, 0]
;

遍历和转换函数

[↑ Up]

库包含大多数流行函数的构造函数,这些函数使用预准备的参数来启动遍历和转换线程的工作。

例如

use \WS\Utils\Collections\Functions\Predicates;

$equal10Predicate = Predicates::equal(10);

$equal10Predicate(11); // false
$equal10Predicate(10); // true

调用函数构造函数 Predicates::equal(10) 将返回一个比较输入参数与值 10 的函数。

库中使用的函数分为以下类型

每种函数类型都必须有对应的接口,以便在特定的流方法中使用。

谓词

[↑ 遍历和转换函数] 一组用于过滤流集合的函数构造函数。所有方法返回具有以下接口的初始化函数: <Fn($el: mixed): bool>。谓词还允许您使用对象属性。例如,对象的 myProperty 属性表示对象中存在名为 myProperty 的公共属性,或者存在名为 getMyPropertygetter 方法。

lock – 锁定

[↑ 谓词]

lock(): Closure; \\ <Fn($el: mixed): bool>

该方法启动一个函数,对于任何一组输入数据,将返回 false。本质上,该方法生成一个流阻塞函数。

use WS\Utils\Collections\CollectionFactory;
use WS\Utils\Collections\Functions\Predicates;

$lockFunction = Predicates::lock();
CollectionFactory::numbers(1, 10)
    ->stream()
    ->filter($lockFunction)
    ->getCollection()
    ->isEmpty() // true
;

notResistance – 传递所有值

[↑ 谓词]

notResistance(): Closure; \\ <Fn($el: mixed): bool>

该方法启动一个函数,对于任何一组输入数据,将返回 true

use WS\Utils\Collections\CollectionFactory;
use WS\Utils\Collections\Functions\Predicates;

$passFunction = Predicates::notResistance();
CollectionFactory::numbers(1, 10)
    ->stream()
    ->filter($passFunction)
    ->getCollection()
    ->size() // 10
;

notNull – 检查值的空性

[↑ 谓词]

notNull(): Closure; \\ <Fn($el: mixed): bool>

该方法启动一个函数,对于任何一组输入数据,将返回 true

use WS\Utils\Collections\CollectionFactory;
use WS\Utils\Collections\Functions\Predicates;

$notNullPassFunction = Predicates::notNull();
CollectionFactory::from([1, 10, null])
    ->stream()
    ->filter($notNullPassFunction)
    ->getCollection()
    ->size() // 2
;

eachEven - 传递偶数调用项

[↑ 谓词]

eachEven(): Closure; \\ <Fn($el: mixed): bool>

该方法启动一个函数,在每次偶数调用时将返回 true,相应地,在其他情况下返回 false

use WS\Utils\Collections\CollectionFactory;
use WS\Utils\Collections\Functions\Predicates;

$evenPassFunction = Predicates::eachEven();
CollectionFactory::from([1, 2, 3, 4, null, false])
    ->stream()
    ->filter($evenPassFunction)
    ->getCollection()
    ->toArray() // 2, 4, false
;

nth – 传递指定元素

[↑ 谓词]

nth($number: int): Closure; \\ <Fn($el: mixed): bool>

该方法启动一个函数,每次 $number 调用将返回 true,相应地,在其他情况下返回 false

use WS\Utils\Collections\CollectionFactory;
use WS\Utils\Collections\Functions\Predicates;

$thirdPassFunction = Predicates::nth(3);
CollectionFactory::from([1, 2, 3, 4, null, false])
    ->stream()
    ->filter($thirdPassFunction)
    ->getCollection()
    ->toArray() // 3, false
;

equal – 等价检查

[↑ 谓词]

equal($value: mixed): Closure; \\ <Fn($el: mixed): bool>

该方法启动一个函数,当集合项与 $value 的值匹配时返回 true

use WS\Utils\Collections\CollectionFactory;
use WS\Utils\Collections\Functions\Predicates;

CollectionFactory::from([1, 2, 3, 4, null, false])
    ->stream()
    ->filter(Predicates::equal(3))
    ->findFirst() // 3
;

lockDuplicated – 锁定重复值

[↑ 谓词]

lockDuplicated(): Closure; \\ <Fn($el: mixed): bool>

该方法启动一个函数,仅对具有唯一成员的调用返回 true

use WS\Utils\Collections\CollectionFactory;
use WS\Utils\Collections\Functions\Predicates;

CollectionFactory::from([3, 2, 3, 4, null, 3])
    ->stream()
    ->filter(Predicates::lockDuplicated())
    ->getCollection()
    ->toArray() // [3, 2, 4, null]
;

小于 – 检查值是否符合“小于”条件

[↑ 谓词]

lessThan($value: scalar): Closure; \\ <Fn($el: scalar): bool>

该方法启动一个用于比较元素与值 $value 的函数。

use WS\Utils\Collections\CollectionFactory;
use WS\Utils\Collections\Functions\Predicates;

CollectionFactory::from([1, 2, 3, 4, null, 3])
    ->stream()
    ->filter(Predicates::lessThan(4))
    ->getCollection()
    ->toArray() // [1, 2, 3, null, 3]
;

小于等于 – 检查值是否符合“小于等于”条件

[↑ 谓词]

lessOrEqual($value: scalar): Closure; \\ <Fn($el: scalar): bool>

该方法启动一个用于比较元素与值 $value 的函数。

use WS\Utils\Collections\CollectionFactory;
use WS\Utils\Collections\Functions\Predicates;

CollectionFactory::from([1, 2, 3, 4, null, 3])
    ->stream()
    ->filter(Predicates::lessOrEqual(2))
    ->getCollection()
    ->toArray() // [1, 2, null]
;

大于 – 检查值是否符合“大于”条件

[↑ 谓词]

greaterThan($value: scalar): Closure; \\ <Fn($el: mixed): bool>

该方法启动一个用于比较元素与值 $value 的函数。

use WS\Utils\Collections\CollectionFactory;
use WS\Utils\Collections\Functions\Predicates;

CollectionFactory::from([1, 2, 3, 4, null, 3])
    ->stream()
    ->filter(Predicates::greaterThan(2))
    ->getCollection()
    ->toArray() // [3, 4, 3]
;

大于等于 – 检查值是否符合“大于等于”条件

[↑ 谓词]

greaterOrEqual($value: scalar): Closure; \\ <Fn($el: mixed): bool>

该方法启动一个用于比较元素与值 $value 的函数。

use WS\Utils\Collections\CollectionFactory;
use WS\Utils\Collections\Functions\Predicates;

CollectionFactory::from([1, 2, 3, 4, null, 3])
    ->stream()
    ->filter(Predicates::greaterOrEqual(2))
    ->getCollection()
    ->toArray() // [2, 3, 4, 3]
;

非 – 检查值是否符合不等式

[↑ 谓词]

not($value: mixed): Closure; \\ <Fn($el: mixed): bool>

该方法启动一个用于检查集合元素与值 $value 不等式的函数。

use WS\Utils\Collections\CollectionFactory;
use WS\Utils\Collections\Functions\Predicates;

CollectionFactory::from([1, 2, 3, 4, null, 3])
    ->stream()
    ->filter(Predicates::not(3))
    ->getCollection()
    ->toArray() // [1, 2, 4, null]
;

在...中 – 检查值是否属于一组值

[↑ 谓词]

in($values: array): Closure; \\ <Fn($el: mixed): bool>

该方法启动一个用于检查元素是否在数组 $values 中的函数。

use WS\Utils\Collections\CollectionFactory;
use WS\Utils\Collections\Functions\Predicates;

CollectionFactory::from([1, 2, 3, 4, null, 3])
    ->stream()
    ->filter(Predicates::in([null, 3]))
    ->getCollection()
    ->toArray() // [3, null, 3]
;

不在...中 – 检查值是否不属于一组值

[↑ 谓词]

notIn($values: array): Closure; \\ <Fn($el: mixed): bool>

该方法启动一个用于检查元素在集合 $values 中不存在的函数。

use WS\Utils\Collections\CollectionFactory;
use WS\Utils\Collections\Functions\Predicates;

CollectionFactory::from([1, 2, 3, 4, null, 3])
    ->stream()
    ->filter(Predicates::notIn([null, 3]))
    ->getCollection()
    ->toArray() // [1, 2, 4]
;

where – 检查对象属性是否等同于某个值

[↑ 谓词]

where($property: string, $value: mixed): Closure; \\ <Fn($el: mixed): bool>

该方法启动一个用于检查元素对象的属性是否等于 $value 的值的函数。

use WS\Utils\Collections\CollectionFactory;
use WS\Utils\Collections\Functions\Predicates;

class ValueObject {
    private $value;
    public function __construct($value) {
        $this->value = $value;
    }
    
    public function getValue() {
        return $this->value;
    }
}

$c = 0;
CollectionFactory::generate(5, static function () use (& $c) {
        return new ValueObject($c++);
    })
    ->stream()
    ->filter(Predicates::where('value', 0))
    ->getCollection()
    ->isEmpty() // false
;

whereNot – 检查对象属性是否不等于某个值

[↑ 谓词]

whereNot($property: string, $value: mixed): Closure; \\ <Fn($el: mixed): bool>

该方法启动一个用于检查元素对象的属性是否不等于 $value 的值的函数。

use WS\Utils\Collections\CollectionFactory;
use WS\Utils\Collections\Functions\Predicates;

class ValueObject {
    private $value;
    public function __construct($value) {
        $this->value = $value;
    }
    
    public function getValue() {
        return $this->value;
    }
}

$c = 0;
CollectionFactory::generate(5, static function () use (& $c) {
        return new ValueObject($c++);
    })
    ->stream()
    ->filter(Predicates::whereNot('value', 0))
    ->getCollection()
    ->toArray() // [#1, #2, #3, #4]
;

whereIn – 检查对象属性是否属于一组值

[↑ 谓词]

whereIn($property: string, $values: array): Closure; \\ <Fn($el: mixed): bool>

该方法启动一个用于检查对象属性的值是否在集合 $values 中的函数。

use WS\Utils\Collections\CollectionFactory;
use WS\Utils\Collections\Functions\Predicates;

class ValueObject {
    private $value;
    public function __construct($value) {
        $this->value = $value;
    }
    
    public function getValue() {
        return $this->value;
    }
}

$c = 0;
CollectionFactory::generate(5, static function () use (& $c) {
        return new ValueObject($c++);
    })
    ->stream()
    ->filter(Predicates::whereIn('value', [0, 4, 9]))
    ->getCollection()
    ->toArray() // [#0, #4]
;

whereNotIn – 检查对象属性是否不属于一组值

[↑ 谓词]

whereNotIn($property: string, $values: array): Closure; \\ <Fn($el: mixed): bool>

该方法启动一个用于检查对象属性的值在集合 $values 中不存在的函数。

use WS\Utils\Collections\CollectionFactory;
use WS\Utils\Collections\Functions\Predicates;

class ValueObject {
    private $value;
    public function __construct($value) {
        $this->value = $value;
    }
    
    public function getValue() {
        return $this->value;
    }
}

$c = 0;
CollectionFactory::generate(5, static function () use (& $c) {
        return new ValueObject($c++);
    })
    ->stream()
    ->filter(Predicates::whereIn('value', [0, 4, 9]))
    ->getCollection()
    ->toArray() // [#0, #4]
;

whereGreaterThan – 检查对象属性是否符合“大于”条件

[↑ 谓词]

whereGreaterThan($property: string, $value: scalar): Closure; \\ <Fn($el: scalar): bool>

该方法启动一个用于比较对象属性的值与 $value 的函数。

use WS\Utils\Collections\CollectionFactory;
use WS\Utils\Collections\Functions\Predicates;

class ValueObject {
    private $value;
    public function __construct($value) {
        $this->value = $value;
    }
    
    public function getValue() {
        return $this->value;
    }
}

$c = 0;
CollectionFactory::generate(5, static function () use (& $c) {
        return new ValueObject($c++);
    })
    ->stream()
    ->filter(Predicates::whereGreaterThan('value', 3))
    ->getCollection()
    ->toArray() // [#4]
;

whereLessThan – 检查对象属性是否符合“小于”条件

[↑ 谓词]

whereLessThan($property: string, $value: scalar): Closure; \\ <Fn($el: scalar): bool>

该方法启动一个用于比较对象属性的值与 $value 的函数。

use WS\Utils\Collections\CollectionFactory;
use WS\Utils\Collections\Functions\Predicates;

class ValueObject {
    private $value;
    public function __construct($value) {
        $this->value = $value;
    }
    
    public function getValue() {
        return $this->value;
    }
}

$c = 0;
CollectionFactory::generate(5, static function () use (& $c) {
        return new ValueObject($c++);
    })
    ->stream()
    ->filter(Predicates::whereLessThan('value', 3))
    ->getCollection()
    ->toArray() // [#0, #1, #2]
;

whereGreaterOrEqual – 检查对象属性是否符合“大于等于”条件

[↑ 谓词]

whereGreaterOrEqual($property: string, $value: scalar): Closure; \\ <Fn($el: scalar): bool>

该方法启动一个用于比较对象属性的值与 $value 的函数。

use WS\Utils\Collections\CollectionFactory;
use WS\Utils\Collections\Functions\Predicates;

class ValueObject {
    private $value;
    public function __construct($value) {
        $this->value = $value;
    }
    
    public function getValue() {
        return $this->value;
    }
}

$c = 0;
CollectionFactory::generate(5, static function () use (& $c) {
        return new ValueObject($c++);
    })
    ->stream()
    ->filter(Predicates::whereGreaterOrEqual('value', 3))
    ->getCollection()
    ->toArray() // [#3, #4]
;

whereLessOrEqual – 检查对象属性是否符合“小于等于”条件

[↑ 谓词]

whereLessOrEqual($property: string, $value: scalar): Closure; \\ <Fn($el: scalar): bool>

该方法启动一个用于比较对象属性的值与 $value 的函数。

use WS\Utils\Collections\CollectionFactory;
use WS\Utils\Collections\Functions\Predicates;

class ValueObject {
    private $value;
    public function __construct($value) {
        $this->value = $value;
    }
    
    public function getValue() {
        return $this->value;
    }
}

$c = 0;
CollectionFactory::generate(5, static function () use (& $c) {
        return new ValueObject($c++);
    })
    ->stream()
    ->filter(Predicates::whereLessOrEqual('value', 3))
    ->getCollection()
    ->toArray() // [#1, #2, #3]
;

比较器

[↑ 遍历和转换函数]

比较函数构造器组。当使用排序方法排列元素时需要比较函数。生成的排序函数具有接口 <Fn($a: mixed, $b: mixed): int>,与 [https://php.ac.cn/manual/ru/function.usort] 具有相同的逻辑。

scalarComparator 标量值比较

[↑ 比较器]

scalarComparator(): Closure; \\ <Fn($a: scalar, $b: scalar): int>

该方法启动一个用于比较两个值的函数。比较函数返回一个整数,该整数小于、等于或大于零,分别表示第一个参数分别小于、等于或大于第二个参数。

use WS\Utils\Collections\CollectionFactory;
use WS\Utils\Collections\Functions\Comparators;

CollectionFactory::generate(5, static function (): int {
        return random_int(0, 10);
    })
    ->stream()
    ->sort(Comparators::scalarComparator())
    ->getCollection()
    ->toArray() // sorted value, for example [2, 3, 6, 7, 8]
;

objectPropertyComparator – 对象属性比较

[↑ 比较器]

objectPropertyComparator($property: string): Closure; \\ <Fn($a: object, $b: object): int>

该方法启动一个用于比较两个对象属性值的函数。比较函数返回一个整数,该整数小于、等于或大于零,分别表示第一个参数分别小于、等于或大于第二个参数。

use WS\Utils\Collections\CollectionFactory;
use WS\Utils\Collections\Functions\Comparators;

class ValueObject {
    private $value;
    public function __construct($value) {
        $this->value = $value;
    }
    
    public function getValue() {
        return $this->value;
    }
}

CollectionFactory::generate(5, static function () {
        return new ValueObject(random_int(0, 10));
    })    
    ->stream()
    ->sort(Comparators::objectPropertyComparator('value'))
    ->getCollection()
    ->toArray() // sorted ValueObject objects, for example [#2, #3, #6, #7, #8]
;

callbackComparator – 定义一个用于比较值的函数

[↑ 比较器]

callbackComparator($fun: <Fn($value: mixed): scalar>): Closure; \\ <Fn($a: mixed, $b: mixed): int>

该方法启动一个根据 $fun 函数处理值来比较两个值的函数。比较函数返回一个整数,该整数小于、等于或大于零,分别表示第一个参数分别小于、等于或大于第二个参数。

use WS\Utils\Collections\CollectionFactory;
use WS\Utils\Collections\Functions\Comparators;

class ValueObject {
    private $value;
    public function __construct($value) {
        $this->value = $value;
    }
    
    public function getValue() {
        return $this->value;
    }
}

CollectionFactory::generate(5, static function () {
        return new ValueObject(random_int(0, 10));
    })    
    ->stream()
    ->sort(Comparators::callbackComparator(static function (ValueObject $valueObject) {
        return $valueObject->getValue();
    }))
    ->getCollection()
    ->toArray() // sorted ValueObject objects, for example [#2, #3, #6, #7, #8]
;

转换器

[↑ 遍历和转换函数]

一组转换元素函数的构造器。转换函数的结果是 <Fn($obj: mixed): mixed>

toPropertyValue 将集合中的每个项目转换为属性值

[↑ 转换器]

toPropertyValue($property: string): Closure; \\ <Fn($obj: object): mixed>

该方法创建一个函数,该函数返回对象属性的值。

use WS\Utils\Collections\CollectionFactory;
use \WS\Utils\Collections\Functions\Converters;

class ValueObject {
    private $value;
    public function __construct($value) {
        $this->value = $value;
    }
    
    public function getValue() {
        return $this->value;
    }
}

CollectionFactory::generate(5, static function (int $index): ValueObject {
        return new ValueObject($index);
    })
    ->stream()
    ->map(Converters::toPropertyValue('value'))
    ->getCollection()
    ->toArray() // [0, 1, 2, 3, 4 ]
;

toProperties 将集合中的每个项目转换为关联数组

[↑ 转换器]

toProperties($names: array<string>): Closure; \\ <Fn($obj: object): array>

该方法启动一个函数,该函数返回一个对象属性的关联数组,其键为属性名称。

use WS\Utils\Collections\CollectionFactory;
use \WS\Utils\Collections\Functions\Converters;

class Person {
    private $name;
    private $surname;
    
    public function __construct(string $name, string $surname) 
    {
        $this->name = $name;
        $this->surname = $surname;
    }
    
    public function getName(): string 
    {
        return $this->name;
    }
    
    public function getSurname(): string
    {
        return $this->surname;
    }
}

CollectionFactory::generate(1, static function (): Person {
        return new Person('Ivan', 'Ivanov');
    })
    ->stream()
    ->map(Converters::toProperties(['name', 'surname']))
    ->getCollection()
    ->toArray() // [['name' => 'Ivan', 'surname' => 'Ivanov']]
;

重新组织者

[↑ 遍历和转换函数]

流转换方法构造函数。与元素转换函数不同,其中原始集合的每个元素对应于新集合的元素,给定第一个元素的位置,流转换方法创建一个具有任意元素数量的派生新集合。

shuffle - 改变集合项的顺序

[↑ 重组器]

shuffle(): Closure; \\ <Fn(): Collection>

该方法启动一个函数,该函数返回一个新集合,其中项目按随机顺序排列。

use \WS\Utils\Collections\CollectionFactory;
use WS\Utils\Collections\Functions\Reorganizers;

CollectionFactory::numbers(5)
    ->stream()
    ->reorganize(Reorganizers::shuffle())
    ->getCollection()
    ->toArray() // for example [0, 3, 1, 2, 4]
;

random - 获取集合的随机元素

[↑ 重组器]

random($count = 1: int): Closure; \\ <Fn(): Collection>

该方法启动一个函数,该函数返回一个新集合,其中包含原始集合中随机边界集的元素。

use \WS\Utils\Collections\CollectionFactory;
use WS\Utils\Collections\Functions\Reorganizers;

CollectionFactory::numbers(5)
    ->stream()
    ->reorganize(Reorganizers::random(2))
    ->getCollection()
    ->toArray() // for example [0, 3]
;

chunk - 将其分割成指定大小的多个集合

[↑ 重组器]

chunk($size: int): Closure; \\ <Fn(): Collection>

该方法启动一个函数,该函数返回一个集合,其元素数量小于或等于 $size

use \WS\Utils\Collections\CollectionFactory;
use WS\Utils\Collections\Functions\Reorganizers;

CollectionFactory::numbers(10)
    ->stream()
    ->reorganize(Reorganizers::chunk(2))
    ->getCollection()
    ->toArray() // for example [[0, 1], [2, 3], ...]
;

collapse - 获取没有额外嵌套级别的集合

[↑ 重组器]

collapse(): Closure; \\ <Fn(): Collection>

该方法启动一个函数,该函数返回一个没有嵌套容器的集合。在此上下文中,容器是可迭代的数据库结构。

use \WS\Utils\Collections\CollectionFactory;
use WS\Utils\Collections\Functions\Reorganizers;

CollectionFactory::generate(3, static function (int $i): array {
        return [$i*2, $i*2 + 1];
    }) // [[0, 1], [2, 3], [4, 5]]
    ->stream()
    ->reorganize(Reorganizers::collapse())
    ->getCollection()
    ->toArray() // for example [0, 1, 2, 3, 4, 5]
;

消费者

[↑ 遍历和转换函数]

消费者函数构造函数。包含一个打印元素值的函数。基本上,每个消费者函数都是在项目源代码中单独开发的。

dump - 列出集合项的值

[↑ 消费者]

dump(): Closure; \\ <Fn(): Collection>

该方法启动一个函数,该函数将传递的值打印到输出流。

use \WS\Utils\Collections\CollectionFactory;
use WS\Utils\Collections\Functions\Consumers;

CollectionFactory::numbers(5)
    ->stream()
    ->each(Consumers::dump()) // dumps each element of collection
;

聚合

[↑ 遍历和转换函数]

by

[↑ 聚合]

$group = Group::by($fieldName): Group;
use \WS\Utils\Collections\CollectionFactory;
use \WS\Utils\Collections\Functions\Group\Group;

$items = [
    ['name' => 'potato', 'type' => 'groceries', 'price' => 25],
    ['name' => 'milk', 'type' => 'groceries', 'price' => 50],
    ['name' => 'taxi', 'type' => 'transport', 'price' => 100],
    ['name' => 'taxi', 'type' => 'transport', 'price' => 70],
    ['name' => 'cinema', 'type' => 'entertainment', 'price' => 30],
    ['name' => 'cinema', 'type' => 'entertainment', 'price' => 20],
];

$result = CollectionFactory::from($items)
    ->stream()
    ->collect(Group::by('type'))
;
/* Result ->
[
    'groceries' => new \WS\Utils\Collections\ArrayList([
        ['name' => 'potato', 'type' => 'groceries', 'price' => 25],
        ['name' => 'milk', 'type' => 'groceries', 'price' => 50],
    ]),
    'transport' => new \WS\Utils\Collections\ArrayList([
       ['name' => 'taxi', 'type' => 'transport', 'price' => 100],
       ['name' => 'taxi', 'type' => 'transport', 'price' => 70],
   ]),
    'entertainment' => new \WS\Utils\Collections\ArrayList([
        ['name' => 'cinema', 'type' => 'entertainment', 'price' => 30],
        ['name' => 'cinema', 'type' => 'entertainment', 'price' => 20],
    ]),
];
*/

addToSet

[↑ 聚合]

Group::addToSet($sourceKey, $destKey): Group;
use \WS\Utils\Collections\CollectionFactory;
use \WS\Utils\Collections\Functions\Group\Group;

$items = [
    ['name' => 'potato', 'type' => 'groceries', 'price' => 25],
    ['name' => 'milk', 'type' => 'groceries', 'price' => 50],
    ['name' => 'taxi', 'type' => 'transport', 'price' => 100],
    ['name' => 'taxi', 'type' => 'transport', 'price' => 70],
    ['name' => 'cinema', 'type' => 'entertainment', 'price' => 30],
    ['name' => 'cinema', 'type' => 'entertainment', 'price' => 20],
];

$aggregation = Group::by('type')->addToSet('name', 'list');
$result = CollectionFactory::from($items)
    ->stream()
    ->collect($aggregation)
;
/* Result ->
[
    'groceries' => ['list' => ['potato', 'milk']],
    'transport' => ['list' => ['taxi']],
    'entertainment' => ['list' => ['cinema']],
];
*/

avg

[↑ 聚合]

Group::avg($sourceKey, $destKey): Group;
use \WS\Utils\Collections\CollectionFactory;
use \WS\Utils\Collections\Functions\Group\Group;

$items = [
    ['name' => 'potato', 'type' => 'groceries', 'price' => 30],
    ['name' => 'milk', 'type' => 'groceries', 'price' => 50],
    ['name' => 'taxi', 'type' => 'transport', 'price' => 100],
    ['name' => 'taxi', 'type' => 'transport', 'price' => 50],
    ['name' => 'cinema', 'type' => 'entertainment', 'price' => 30],
    ['name' => 'cinema', 'type' => 'entertainment', 'price' => 30],
];

$aggregation = Group::by('type')->avg('price', 'avg');
$result = CollectionFactory::from($items)
    ->stream()
    ->collect($aggregation)
;
/* Result ->
[
    'groceries' => ['avg' => 40],
    'transport' => ['avg' => 75],
    'entertainment' => ['avg' => 30],
];
*/

count

[↑ 聚合]

Group::count($destKey): Group;
use \WS\Utils\Collections\CollectionFactory;
use \WS\Utils\Collections\Functions\Group\Group;

$items = [
    ['name' => 'potato', 'type' => 'groceries', 'price' => 30],
    ['name' => 'milk', 'type' => 'groceries', 'price' => 50],
    ['name' => 'tea', 'type' => 'groceries', 'price' => 50],
    ['name' => 'taxi', 'type' => 'transport', 'price' => 100],
    ['name' => 'cinema', 'type' => 'entertainment', 'price' => 30],
    ['name' => 'cinema', 'type' => 'entertainment', 'price' => 30],
];

$aggregation = Group::by('type')->count('total');
$result = CollectionFactory::from($items)
    ->stream()
    ->collect($aggregation)
;
/* Result ->
[
    'groceries' => ['total' => 3],
    'transport' => ['total' => 1],
    'entertainment' => ['total' => 2],
];
*/

first

[↑ 聚合]

Group::first($sourceKey, $destKey): Group;
use \WS\Utils\Collections\CollectionFactory;
use \WS\Utils\Collections\Functions\Group\Group;

$items = [
    ['name' => 'potato', 'type' => 'groceries', 'price' => 30],
    ['name' => 'milk', 'type' => 'groceries', 'price' => 50],
    ['name' => 'taxi', 'type' => 'transport', 'price' => 100],
    ['name' => 'airplane', 'type' => 'transport', 'price' => 50],
    ['name' => 'Knicks game', 'type' => 'entertainment', 'price' => 300],
    ['name' => 'cinema', 'type' => 'entertainment', 'price' => 30],
];

$aggregation = Group::by('type')->first('name', 'item');
$result = CollectionFactory::from($items)
    ->stream()
    ->collect($aggregation)
;
/* Result ->
[
    'groceries' => ['item' => 'potato'],
    'transport' => ['item' => 'taxi'],
    'entertainment' => ['item' => 'Knicks game'],
];
*/

last

[↑ 聚合]

Group::last($sourceKey, $destKey): Group;
use \WS\Utils\Collections\CollectionFactory;
use \WS\Utils\Collections\Functions\Group\Group;

$items = [
    ['name' => 'potato', 'type' => 'groceries', 'price' => 30],
    ['name' => 'milk', 'type' => 'groceries', 'price' => 50],
    ['name' => 'taxi', 'type' => 'transport', 'price' => 100],
    ['name' => 'airplane', 'type' => 'transport', 'price' => 50],
    ['name' => 'Knicks game', 'type' => 'entertainment', 'price' => 300],
    ['name' => 'cinema', 'type' => 'entertainment', 'price' => 30],
];

$aggregation = Group::by('type')->last('name', 'item');
$result = CollectionFactory::from($items)
    ->stream()
    ->collect($aggregation)
;
/* Result ->
[
    'groceries' => ['item' => 'milk'],
    'transport' => ['item' => 'airplane'],
    'entertainment' => ['item' => 'cinema'],
];
*/

max

[↑ 聚合]

Group::max($sourceKey, $destKey): Group;
use \WS\Utils\Collections\CollectionFactory;
use \WS\Utils\Collections\Functions\Group\Group;

$items = [
    ['name' => 'potato', 'type' => 'groceries', 'price' => 30],
    ['name' => 'milk', 'type' => 'groceries', 'price' => 50],
    ['name' => 'taxi', 'type' => 'transport', 'price' => 100],
    ['name' => 'airplane', 'type' => 'transport', 'price' => 50],
    ['name' => 'Knicks game', 'type' => 'entertainment', 'price' => 300],
    ['name' => 'cinema', 'type' => 'entertainment', 'price' => 30],
];

$aggregation = Group::by('type')->max('price', 'max');
$result = CollectionFactory::from($items)
    ->stream()
    ->collect($aggregation)
;
/* Result ->
[
    'groceries' => ['max' => 50],
    'transport' => ['max' => 100],
    'entertainment' => ['max' => 300],
];
*/

min

[↑ 聚合]

Group::min($sourceKey, $destKey): Group;
use \WS\Utils\Collections\CollectionFactory;
use \WS\Utils\Collections\Functions\Group\Group;

$items = [
    ['name' => 'potato', 'type' => 'groceries', 'price' => 30],
    ['name' => 'milk', 'type' => 'groceries', 'price' => 50],
    ['name' => 'taxi', 'type' => 'transport', 'price' => 100],
    ['name' => 'airplane', 'type' => 'transport', 'price' => 50],
    ['name' => 'Knicks game', 'type' => 'entertainment', 'price' => 300],
    ['name' => 'cinema', 'type' => 'entertainment', 'price' => 30],
];

$aggregation = Group::by('type')->min('price', 'min');
$result = CollectionFactory::from($items)
    ->stream()
    ->collect($aggregation)
;
/* Result ->
[
    'groceries' => ['min' => 30],
    'transport' => ['min' => 50],
    'entertainment' => ['min' => 30],
];
*/

sum

[↑ 聚合]

Group::sum($sourceKey, $destKey): Group;
use \WS\Utils\Collections\CollectionFactory;
use \WS\Utils\Collections\Functions\Group\Group;

$items = [
    ['name' => 'potato', 'type' => 'groceries', 'price' => 30],
    ['name' => 'milk', 'type' => 'groceries', 'price' => 50],
    ['name' => 'taxi', 'type' => 'transport', 'price' => 100],
    ['name' => 'airplane', 'type' => 'transport', 'price' => 50],
    ['name' => 'Knicks game', 'type' => 'entertainment', 'price' => 300],
    ['name' => 'cinema', 'type' => 'entertainment', 'price' => 30],
];

$aggregation = Group::by('type')->sum('price', 'spent');
$result = CollectionFactory::from($items)
    ->stream()
    ->collect($aggregation)
;
/* Result ->
[
    'groceries' => ['spent' => 80],
    'transport' => ['spent' => 150],
    'entertainment' => ['spent' => 330],
];
*/

addAggregator

[↑ 聚合]

Group::addAggregator($destKey, $callbackFn): Group;
use \WS\Utils\Collections\CollectionFactory;
use \WS\Utils\Collections\Functions\Group\Group;
use \WS\Utils\Collections\Collection;

$items = [
    ['name' => 'potato', 'type' => 'groceries', 'price' => 30],
    ['name' => 'milk', 'type' => 'groceries', 'price' => 50],
    ['name' => 'taxi', 'type' => 'transport', 'price' => 100],
    ['name' => 'airplane', 'type' => 'transport', 'price' => 50],
    ['name' => 'Knicks game', 'type' => 'entertainment', 'price' => 300],
    ['name' => 'cinema', 'type' => 'entertainment', 'price' => 30],
];

$aggregation = Group::by('type')->addAggregator('names', function (Collection $collection) { 
    $result = [];
    foreach ($collection as $item) {
        $result[] = $item['name'];
    }
    return implode(', ', $result);
});
$result = CollectionFactory::from($items)
    ->stream()
    ->collect($aggregation)
;
/* Result ->
[
    'groceries' => ['names' => 'potato, milk'],
    'transport' => ['names' => 'taxi, airplane'],
    'entertainment' => ['names' => 'Knicks game, cinema'],
];
*/

所有聚合器都可以相互结合以获得所需的结果

use \WS\Utils\Collections\CollectionFactory;
use \WS\Utils\Collections\Functions\Group\Group;

$items = [
    ['name' => 'potato', 'type' => 'groceries', 'price' => 30],
    ['name' => 'milk', 'type' => 'groceries', 'price' => 50],
    ['name' => 'taxi', 'type' => 'transport', 'price' => 100],
    ['name' => 'airplane', 'type' => 'transport', 'price' => 50],
    ['name' => 'Knicks game', 'type' => 'entertainment', 'price' => 300],
    ['name' => 'cinema', 'type' => 'entertainment', 'price' => 30],
];

$aggregation = Group::by('type')->avg('price', 'avg')->min('price', 'min')->max('price', 'max');
$result = CollectionFactory::from($items)
    ->stream()
    ->collect($aggregation)
;
/* Result ->
[
    'groceries' => ['avg' => 40, 'min' => 30, 'max' => 50],
    'transport' => ['avg' => 75, 'min' => 50, 'max' => 100],
    'entertainment' => ['avg' => 165, 'min' => 30, 'max' => 300],
];
*/