ft/sets

此包已被废弃,不再维护。未建议替代包。

为 Sets 提供的轻量级灵活的 PHP hashtable 包装包

1.0.1 2023-02-14 02:24 UTC

This package is auto-updated.

Last update: 2024-04-14 05:40:12 UTC


README

PHP 轻量级 hashtable(关联数组)包装包,用于 Set 数据结构。

Set 是一个有效的容器,用于存储唯一值。

思考

什么是“唯一”的?

唯一性是通过该包对任何给定输入的哈希值来确定的。哈希值内部生成以确保一致性。然后使用哈希值作为识别 hashtables 元素/值的方式

为什么要创建内部哈希码? 为什么不使用内置的 spl_object_hashhash

有许多原因不依赖于这些值,但基本上,它们不能保证唯一性。

例如

$aStd = new stdClass;
$aStd->foo = "foobar";

$bStd = new stdClass;
$bStd->foo = "foobar";

这两个对象被认为是相等的,因为它们具有相同数量的属性,属性值相同,并且它们都是 stdClass 对象的派生。

然而,两个哈希的结果

var_dump(spl_object_hash($aStd)); //00000000000000010000000000000000
var_dump(spl_object_hash($bStd)); //00000000000000020000000000000000

此外,spl_object_hash 仅允许对象,而 hash|md5 等 预期字符串,并非所有对象都包含 __toString() 逻辑。

简而言之,这是一个非常复杂的问题,因为唯一性永远不能得到保证,但哈希 可以应该 限制潜在的冲突,该包正是为此而奋斗

安装

composer require ft/sets

集合类

Set

一个可以容纳零个或多个任何数据类型元素的容器

类图
classDiagram
    class Countable {
        <<interface>>
        public count(): int
    }
    class Traversable {
        <<interface>>
    }
    class Iterator {
        <<interface>>
        public rewind(): void
        public current(): mixed
        public key(): mixed
        public next(): void
        public valid(): bool
    }
    Countable <|-- Set
    Traversable <|-- Set
    Iterator <|-- Set
    class Set {
        __construct(array $elements =[], bool $silently_ignore_null = false)
        add(mixed $element): bool
        addAll(array $array)
        remove(mixed $element) : bool
        removeAll(array $array)
        clear()
        indexOf(array|string|int|float|bool|Comparable $value): int
        union(Set $b): Set
        intersection(Set $b): Set
        difference(Set $b): Set
        subset(Set $b): bool
        pop(): mixed
        shift(): mixed
        last(): mixed
        first(): mixed
        isEmpty(): bool
        size(): int
        equals(Set $b): bool
        contains(mixed $element): bool
        filter(callable|SetPredicate $predicate): Set
        anyMatch(callable|SetPredicate $predicate): bool
        allMatch(callable|SetPredicate $predicate): bool
        noneMatch(callable|SetPredicate $predicate): bool
        choose(int $quantity): mixed
        levenshtein(string $query): ?string
        toArray(array $keys = []): array
        map(callable $callable) : Set
        flatten(int $depth = 1): Set
    }

StrictSet

Set 的一个子类,它只允许在给定实例中存在相同的数据类型

注意 StrictSet 中添加的第一个元素决定了可以随后添加的元素类型

当添加的 StrictSet 元素不是相同类型时,将抛出 InvalidArgumentException。甚至不允许元素的子类

SortedSet

有序集合是对值进行升序或降序排序的集合,如果选择降序。因此,有序集合必须包含相同的元素(类似于 StrictSet

为数值数据类型提供了额外的函数

警告 字符串比较没有地区集成,这超出了本库的范围

类图
classDiagram
    class Set
    class StrictSet
    Set --|> StrictSet
    StrictSet --|> SortedSet
    class SortedSet {
        partition(int $offset, ?int $length = null): SortedSet
        ceiling(string|int|float $value): string | int | float | null
        floor(string|int|float $value): string | int | float | null
        higher(string|int|float $value): string | int | float | null
        lower(string|int|float $value): string | int | float | null
        headSet(string|int|float $value): string | int | float | null
        tailSet(string|int|float $value): string | int | float | null
        reverse(string|int|float $value): string | int | float | null
    }

示例

Set

$car = new stdClass;
$car->make = 'toyota';

$set = new Set;
$set->add(1);
$set->add(2.);
$set->add('foobar');
$set->add('foobar');
$set->add(new stdClass);
$set->add(new stdClass);
$set->add(true);
$set->add(true === true);
$set->add($car);

var_dump($set->toArray());
/*
array(4) {
  [0] => int(1)
  [1] => double(2)
  [2] => string(6) "foobar"
  [3] => class stdClass#2 (0) { }
  [4] => class stdClass#3 (1) {
    public $make => string (6) "toyota"
  }
}
*/

SortedSet

$set = new SortedSet;

$set->addAll([
    'pea',
    'pineapple',
    'apple',
    'apple',
    'orange',
    'apple',
    'banana',
    'potato',
    'radish',
    'carrot',
    'pea',
    'apple',
    'pea',
    'bean'
]);

var_dump($set->toArray());
/*
array(9) {
  [0] => string(5) "apple"
  [1] => string(6) "banana"
  [2] => string(4) "bean"
  [3] => string(6) "carrot"
  [4] => string(6) "orange"
  [5] => string(3) "pea"
  [6] => string(9) "pineapple"
  [7] => string(6) "potato"
  [8] => string(6) "radish"
}
*/