jakewhiteley/php-sets

PHP 中类似 Java 集合数据结构的实现。集合是一个可迭代的序列化数据结构,允许严格类型存储唯一值。

1.3.0 2023-05-31 20:25 UTC

This package is auto-updated.

Last update: 2024-08-30 02:05:34 UTC


README

Travis (.com) Coveralls github

php-set-data-structure

Java 集合数据结构的 PHP 实现。

集合简单来说是一组可以按插入顺序迭代的唯一事物。因此,集合的一个显著特征是它不包含重复项。

实现基于 EMCA 6 JavaScript 中集合的 MDN JS 参考 MDN JS Reference

集合需要 PHP 版本 7.4 或更高。

安装

您可以通过此页面的发布链接下载最新版本。

PHP-Sets 通过 Composer 提供,运行以下命令

composer require jakewhiteley/php-sets

然后按如下方式将库包含到您的项目中

include('vendor/autoload.php');

use PhpSets\Set;

基本用法

创建一个集合

创建集合时,您可以插入初始值或将其保持为空。

$set = new Set(1, 2, 3);
$emptySet = new Set();

集合不能包含重复的值,并且值按照插入顺序存储。

// $set contains [1, 2, 3] as duplicates are not stored
$set = new Set(1, 2, 1, 3, 2);

如果您有一个元素数组,您可以直接传递该数组,或者展开该数组。

$set = new Set([1, 2, 1, 3, 2]);

$array = [1, 2, 1, 3, 2];
$set = new Set(...$array);

添加值

通过 add() 方法可以将任何类型的值(包括对象、数组和其他 Sets)添加到集合中。

值得注意的是,唯一性是基于 严格类型 的,因此 (string) '1' !== (int) 1 !== (float) 1.0。这也适用于集合中的对象,即使属性等相同,具有类A的对象也不等于具有类B的对象。

// create empty Set
$set = new Set(); 

$set->add('a');
// $set => ['a']

$set->add(1);
// $set => ['a', 1]

由于 Sets 实现了 ArrayAccess 接口,您也可以像标准数组一样添加值。

$set = new Set();

$set[] = 1;
$set[] = 'foo';
// $set => [1, 'foo']


// You can also replace values by key, provided the new value is unique within the Set
$set[0] = 2;
// $set => [2, 'foo']

// If a key is not currently in the array, the value is appended to maintain insertion order
$set[4] = 'foo';
// $newSet => [2, 'foo', 'foo']

删除值

您可以通过 delete() 单独删除值,或者通过 clear() 方法一次性删除所有值。

$set = new Set(1, 2, 3);

$set->delete(2);
// $set => [1, 3]

$set->clear();
// $set => []

您也可以通过 ArrayAccess 删除方法

$set = new Set(1, 2, 3);

unset($set[0]);
// $set => [2, 3]

检查值是否存在

您可以通过 has($value) 方法轻松检查集合是否包含值。

与其他方法一样,这是一个 严格类型 测试。

$set = new Set('a', [1, 2], 1.0);

$set->has('a');      // true
$set->has([1, 2]);   // true
$set->has(1);        // false
$set->has([1, '2']); // false
$set->has('foo');    // false

计算元素数量

这是通过 count 方法完成的

$set = new Set(1, 2, 3);

echo $set->count(); // 3

迭代

迭代集合有多种方法

  • 类似于传统 PHP 数组
  • 使用 entries() 返回 PHP 的 ArrayIterator 实例
  • 使用 each() 和提供的回调函数
  • 使用 values(),它返回集合的传统 PHP 数组版本

作为传统数组

集合对象扩展了 ArrayObject,可以像正常数组一样迭代

$set = new Set(1, 2);

foreach ($set as $val) {
    print($val);
}

或者,如果您愿意,您也可以迭代 $set->values()

使用 entries()

entries() 方法返回一个 ArrayIterator 对象。

$iterator = $set->entries();

while ($iterator->valid()) {
    echo $iterator->current();
    $iterator->next();
}

使用 each($callback, ...$args)

您还可以通过提供的 可调用 方法遍历一个 Set

回调函数将以当前项作为参数 1,并以任何其他指定的参数作为后续参数调用。

function cb($item, $parameter) {
  echo $item * $parameter;
}

$set = new Set(1, 2);

$set->each('cb', 10);
// prints 10 20

集合操作

并集

将第二个 Set 追加到给定的 Set 中,而不创建重复项

$a = new Set(1, 2, 3);
$b = new Set(2, 3, 4);

$merged = $a->union($b);

print_r($merged->values()); // [1, 2, 3, 4]

差集

difference() 方法将返回一个新的 Set,其中包含原始 Set 中存在但不在另一个 Set 中的值。

这也可以称为 相对补集

$a = new Set(1, 2, 3, 4);
$b = new Set(3, 4, 5, 6);

print_r($a->difference($b)->values()); // [1, 2]
print_r($b->difference($a)->values()); // [5, 6]

对称差集

symmetricDifference() 方法也会返回一个新的 Set,但它与 difference 方法不同,因为它将返回两个 Set 之间的所有不同值。

$a = new Set(1, 2, 3, 4);
$b = new Set(3, 4, 5, 6);

print_r($a->symmetricDifference($b)->values()); // [1, 2, 5, 6]

交集

返回一个新 Set,其中包含两个集合之间共同(存在于两个集合中)的项

$a = new Set(1, 2, 3);
$b = new Set(2, 3, 4);

$intersect = $a->intersect($b);

print_r($intersect->values()); // [2, 3]

子集

isSupersetOf 方法返回一个 bool,指示给定的 Set 是否是当前 Set 的子集。

值的顺序不重要,但子集必须只包含原始 Set 中存在的项

$a = new Set(1, 2, 3);
$b = new Set(2, 3);

var_Dump($b->isSupersetOf($a)); // true
var_Dump($a->isSupersetOf($b)); // false

集合家族操作

如果我们有一组集合,例如 { { 1,2,3 }, { 3,4,5 } , { 3, 5, 6, 7 } },在集合论中通常称为 集合族,我们可以取该族的所有并集和交集。也就是说,( { 1, 2, 3 } 并 { 3, 4, 5 } ) 并 { 3, 5, 6, 7 },同样也适用于交集。在集合论中,使用一个大并集和交集符号来表示这个目的。

请注意,目前,这些操作是通过迭代调用上述的 unionintersect 方法实现的。更有效的实现是可能的,并受到欢迎。

集合族的并集

目前,集合族需要是一个包含 Set 对象的数组

$set1 = Set(1, 2, 3);
$set2 = Set(3, 4, 5);
$set2 = Set(5, 1, 6);

$set_union = Set::familyUnion([$set1, $set2]); // [1, 2, 3, 4, 5, 6]

集合族的交集

familyUnion 一样,集合族需要是一个包含 Set 对象的数组

$set1 = Set(1,2,3);
$set2 = Set(3,4,5);
$set_family = [ $set1, $set2 ];
$set_intersection = Set::familyIntersection($set_family);

请注意,与集合论不同,取空数组的交集的结果是一个空数组。(在集合论中,空族的交集是未定义的,因为它将是 '所有集合的集合'。)

贡献

欢迎贡献和更改!只需打开一个问题或提交一个 PR 💪