crell / ordered-collection
一个快速且健壮的优先级和拓扑排序库。
Requires
- php: ~8.1
Requires (Dev)
- phpbench/phpbench: ^1.2
- phpstan/phpstan: ^1.10
- phpunit/phpunit: ^10.4
This package is auto-updated.
Last update: 2024-09-15 17:59:20 UTC
README
有序集合就是它所说的那样;它是一个基于优先级值或拓扑排序(之前/之后)对任意项进行排序的灵活工具。它包含两个实现,OrderedCollection
和 MultiOrderedCollection
。前者稍微快一些,而后者功能更强大。
有关优先级和拓扑排序的更多信息,请参阅比较结果的这篇基准博客文章。
OrderedCollection
OrderedCollection
支持通过整数优先级或单个之前/之后值对项目进行排序。内部,它将之前/之后信息转换为优先级值,然后根据优先级对整个列表进行排序。这通常比拓扑排序更快,但不能处理每个项目超过一个之前/之后条目,也不能检测之前/之后排序中的循环依赖。
首先,创建一个新的集合
use Crell\OrderedCollection\OrderedCollection; $collection = new OrderedCollection();
现在,可以使用 addItem()
、addItemBefore()
和 addItemAfter()
将任意项目添加到集合中。每个项目可以是任意值,它们不需要是同一类型。
添加项目时,您可以提供 $id
。如果不提供,将自动创建一个。由该方法返回的 ID 将是所使用的 ID。ID 对于之前/之后排序是必要的。如果 ID 已经在使用中,将自动添加一个数字后缀以确保唯一性。
// Adds an item with priority 3, and a random ID will be generated. $kirk = $collection->addItem('James T. Kirk', 3); // Adds an item with priority 5, and an ID of "picard". $picard = $collection->addItem('Jean-Luc Picard', 5, 'picard'); // Adds an item to some somewhere after another item, by its ID. // The ID for it will be auto-generated $sisko = $collection->addItemAfter($picard, 'Benjamin Sisko'); // Adds an item to some somewhere before another item, by its ID. // The new item's ID will be "janeway". $janeway = $collection->addItemBefore($kirk, 'Katheryn Janeway', 'janeway');
一旦添加了项目,它们将在第一次迭代集合时自动排序。OrderedCollection
实现了 \IteratorAggregate
,因此您可以使用 foreach()
或 iterator_to_array()
来获取值。
foreach ($collection as $item) { print $item . PHP_EOL; }
在这种情况下,输出将如下所示
Katheryn Janeway
Jean-Luc Picard
Benjamin Sisko
James T. Kirk
MultiOrderedCollection
这个第二个、更健壮的选项与 OrderedCollection
非常相似,并且两者都实现了相同的 OrderableCollection
接口。然而,MultiOrderedCollection
有一个额外的 add()
方法,它可以处理优先级、之前和之后排序,并支持同一项目上的多个之前/之后条目。因此,建议使用 add()
与 MultiOrderedCollection
,尽管公共接口在两者上仍将正常工作。
MultiOrderedCollection
将所有优先级转换为“之前”条目,然后对集合进行拓扑排序。这可能会稍微慢一些,但它支持单个项目上的多个之前/之后指令,并且还会检测循环依赖,这会触发一个 CycleFound
异常。
add()
方法的签名如下所示
add( mixed $item, ?string $id = null, ?int $priority = null, array $before = [], array $after = [], ): string
返回值是分配给值的 ID,然后可以用于之前/之后排序。值得注意的是,$before
和 $after
参数接受一个数组,而不是单个 ID。此外,由于有许多选项,强烈建议使用命名参数。
上面的示例在 MultiOrderedCollection
上看起来是这样的
use Crell\OrderedCollection\MultiOrderedCollection; $collection = new MultiOrderedCollection(); // Adds an item with priority 3, and a random ID will be generated. $kirk = $collection->add('James T. Kirk', priority: 3); // Adds an item with priority 3, and an ID of "picard". $picard = $collection->add('Jean-Luc Picard', priority: 5, id: 'picard'); // Adds an item to some somewhere after another item, by its ID. // The ID for it will be auto-generated $sisko = $collection->add('Benjamin Sisko', after: ['picard']); // Adds an item to some somewhere before another item, by its ID. // The new item's ID will be "janeway". $janeway = $collection->add('Katheryn Janeway', before: [$kirk], id: 'janeway'); foreach ($collection as $item) { print $item . PHP_EOL; }
在这种情况下,输出将与之前相同。
Katheryn Janeway
Jean-Luc Picard
Benjamin Sisko
James T. Kirk
保证
OrderedCollection
和 MultiOrderedCollection
对返回的值列表提供以下保证
- 优先级整数更高的项将排在优先级整数较低的项之前。
- 列出为“在...之前”的项将排在那个项之前。
- 列出为“在...之后”的项将排在那个项之后。
它们不提供以下保证,因此虽然可能发生,但不应该依赖它们。
- 排在另一个项“之前”的项可能不会立即排在前面。它们之间可能还有其他项。
- 排在另一个项“之后”的项可能不会立即排在后面。它们之间可能还有其他项。
- 添加项的顺序无关紧要。在
OrderedCollection
中,具有相同优先级的项通常会按照它们添加的顺序返回,但这不是保证。在MultiOrderedCollection
中,它们可能不会按照添加的顺序返回。简而言之,如果您关心顺序,请明确指定。
类型
在排序过程中根本不使用正在排序的项。虽然上面的例子显示了字符串,但您可以使用数组、对象、字符串、数字或您想要的任何其他内容。它们可以是同一类型,也可以是不同类型。集合对象不关心。
变更日志
有关最近更改的更多信息,请参阅变更日志。
测试
$ composer test
贡献
安全
如果您发现任何与安全相关的问题,请使用GitHub安全报告表而不是问题队列。
鸣谢
许可协议
小于GPL版本3或更高版本。请参阅许可文件以获取更多信息。