mf / collections-php
PHP 的集合 - 它基本上是对经典数组结构的语法糖,允许你将其用作经典数组,但增加了些酷炫的功能。
8.3.0
2023-12-13 08:13 UTC
Requires
- php: ^8.2
- ext-mbstring: *
- beberlei/assert: ^3.0
Requires (Dev)
- ergebnis/composer-normalize: ^2.40
- lmc/coding-standard: ^3.3
- mockery/mockery: ^1.6.7
- php-parallel-lint/php-parallel-lint: ^1.3.2
- phpstan/extension-installer: ^1.3.1
- phpstan/phpstan: ^1.10.49
- phpstan/phpstan-beberlei-assert: ^1.1.2
- phpstan/phpstan-mockery: ^1.1.1
- phpstan/phpstan-phpunit: ^1.3.15
- phpunit/phpunit: ^10.5.3
- symfony/var-dumper: ^7.0
- dev-master
- 8.3.0
- 8.2.0
- 8.1.1
- 8.1.0
- 8.0.0
- v7.x-dev
- 7.2.0
- 7.1.1
- 7.1.0
- 7.0.0
- 6.1.1
- 6.1.0
- 6.0.0
- v5.x-dev
- 5.0.1
- 5.0.0
- 4.0.0
- 3.18.0
- 3.17.0
- 3.16.1
- 3.16.0
- 3.15.0
- 3.14.0
- 3.13.0
- 3.12.0
- 3.11.0
- 3.10.0
- 3.9.0
- 3.8.0
- 3.7.0
- 3.6.0
- 3.5.1
- 3.5.0
- 3.4.2
- 3.4.1
- 3.3.0
- 3.2.2
- 3.2.1
- 3.2.0
- 3.1.1
- 3.0.1
- 3.0.0
- 2.1.0
- 2.0.1
- 2.0.0
- 1.0.0
- dev-feature/update-cs
This package is auto-updated.
Last update: 2024-09-14 08:45:48 UTC
README
它基本上是对经典数组结构的语法糖,允许你将其用作经典数组,但增加了些酷炫的功能。
目录
安装
composer require mf/collections-php
要求
PHP ^8.2
基本接口
有关更多详细信息,请参阅 文档。
IEnumerable
ICollection
IList
列表是一个有序(可能是不可变)的同类型元素序列。
IMap
映射是一个有序(可能是不可变)的键值对序列。
ISeq
序列是一个逻辑上的元素序列,所有元素都是同一类型。
- 扩展
ICollection
- 参见不可变序列
ITuple
元组是一组无名称但有序的值,可能具有不同的类型。
- 扩展
IEnumerable
,ArrayAccess
,Stringable
- 参见不可变元组
可变集合
接口
Mutable\Generic\ICollection
,Mutable\Generic\IList
,Mutable\Generic\IMap
Mutable\Generic\ListCollection
- 实现
Mutable\Generic\IList
- 尽可能懒地实现
Mutable\Generic\Map
- 实现
Mutable\Generic\IMap
- 尽可能懒地实现
Mutable\Generic\PrioritizedCollection
- 实现
IEnumerable
- 通过
优先级
持有具有泛型
类型的项 - 尽可能懒地实现
优先级策略示例
对于只想应用 第一个能完成你想要的策略
的情况。你可以动态地添加策略,并在以后按 优先级
应用它们。
// initialization of strategies /** @phpstan-var PrioritizedCollection<StrategyInterface> $strategies */ $strategies = new PrioritizedCollection(); $strategies->add(new DefaultStrategy(), 1); // added later $strategies->add(new SpecialStrategy(), 100); // find and apply first suitable strategy /** @var StrategyInterface $strategy */ foreach ($strategies as $strategy) { if ($strategy->supports($somethingStrategic)) { return $strategy->apply($somethingStrategic); } }
不可变集合
- 不可变集合实例的
内部状态
将永远不会从外部(它是只读的
)改变
$list = new Immutable\ListCollection(); $listWith1 = $list->add(1); // $list != $listWith1 echo $list->count(); // 0 echo $listWith1->count(); // 1
$list
仍然是空的Immutable\ListCollection
$listWith1
是具有值1
的新Immutable\ListCollection
实例
接口
Immutable\Generic\ICollection
,Immutable\Generic\IList
,Immutable\Generic\IMap
,Immutable\Generic\ISeq
,Immutable\ITuple
Immutable\Generic\ListCollection
- 实现
Immutable\Generic\IList
- 尽可能懒地实现
Immutable\Generic\Map
- 实现
Immutable\Generic\IMap
- 尽可能懒地实现
Immutable\Seq
- 实现
Immutable\Generic\ISeq
- 越懒越好(甚至可能是
无限
)
$seq = Seq::infinite() // 1, 2, ... ->filter(fn ($i) => $i % 2 === 0) // 2, 4, ... ->skip(2) // 6, 8, ... ->map(fn ($i) => $i * $i) // 36, 64, ... ->takeWhile(fn ($i) => $i < 100) // 36, 64 ->reverse() // 64, 36 ->take(1); // 64 // for now the Sequence is still lazy // this will generate (evaluate) the values $array = $seq->toArray(); // [64]
不可变\泛型\KVPair
- 始终包含一个
键
和一个值
- 键限制为
int|string
,因此它可以作为foreach
中的键使用 - 可以包含任何值
不可变\元组
- 实现
不可变\ITuple
- 至少必须有2个值(否则它只是一个单个值)
- 尽可能懒地实现
- 允许
解构
、匹配
和解析
/格式化
- 可以包含任何标量值和/或数组
- 在
元组
的字符串表示中,数组值必须由;
(而不是,
)分隔
- 在
解析
Tuple::parse('(foo, bar)')->toArray(); // ['foo', 'bar'] Tuple::parse('("foo, bar", boo)')->toArray(); // ['foo, bar', 'boo'] Tuple::parse('(1, "foo, bar", true)')->toArray(); // [1, 'foo, bar', true] Tuple::parse('(1, [2; 3], [four; "Five"])')->toArray(); // [1, [2, 3], ['four', 'five']]
匹配和比较
Tuple::from([1, 1])->match('int', 'int'); // true Tuple::from([1, 2, 3])->isSame(Tuple::of(1, 2, 3)); // true Tuple::of(10, 'Foo', null)->match('int', 'string', '?string'); // true Tuple::of(10, [9, 8])->match('int', 'array'); // true
解析和匹配
Tuple::parseMatch('(foo, bar)', 'string', 'string')->toArray(); // ['foo', 'bar'] Tuple::parseMatchTypes('(foo, bar)', ['string', 'string'])->toArray(); // ['foo', 'bar'] // invalid types Tuple::parseMatch('(foo, bar, 1)', 'string', 'string'); // throws \InvalidArgumentException "Given tuple does NOT match expected types (string, string) - got (string, string, int)"
格式化
Tuple::from([1, 'foo', null])->toString(); // '(1, "foo", null)' // for URL Tuple::from(['foo', 'bar'])->toStringForUrl(); // '(foo,bar)' Tuple::from(['foo-bar', 'boo'])->toStringForUrl(); // '(foo-bar,bar)' Tuple::from(['mail', 'a@b.com'])->toStringForUrl(); // '(mail,"a@b.com")'
解构
$tuple = Tuple::of('first', 2, 3); // ('first', 2, 3) $first = $tuple->first(); // 'first' $second = $tuple->second(); // 2 [$first, $second] = $tuple; // $first = 'first'; $second = 2 [,, $third] = $tuple; // 3
解包
sprintf('Title: %s | Value: %s', ...Tuple::of('foo', 'bar')); // "Title: foo | Value: bar"
合并
- 合并
元组
将自动扁平化(请参见下面的最后一个示例)
$base = Tuple::of('one', 'two'); // ('one', 'two') $upTo3 = Tuple::merge($base, 'three'); // ('one', 'two', 'three') $upTo4 = Tuple::merge($base, '3', 'four'); // ('one', 'two', '3', 'four') $upTo5 = Tuple::merge($base, ['3', '4'], '5'); // ('one', 'two', ['3', '4'], '5') $upTo5 = Tuple::merge($base, Tuple::of('3', '4'), '5'); // ('one', 'two', '3', '4', '5')
合并和匹配
$base = Tuple::of('one', 'two'); // ('one', 'two') $upTo3 = Tuple::mergeMatch(['string', 'string', 'int'], $base, 3); // ('one', 'two', 3) // invalid types Tuple::mergeMatch(['string', 'string'], $base, 3); // throws \InvalidArgumentException "Merged tuple does NOT match expected types (string, string) - got (string, string, int)."
序列和懒映射
- 如果你的
序列
被多次映射和过滤(为了可读性),这不是问题map -> map -> filter -> map -> filter -> map
将仅迭代集合一次(一次性应用所有修饰符)- 此修改是在触发另一个方法时进行的,因此添加新修饰符是
原子
操作
- 所有值都是即时生成的,因此它可能最终会抛出内存不足异常
下一个版本的计划
- 在单元测试中使用
Symfony/Stopwatch
- 更好的文档(当前)