ihor/nspl

非标准 PHP 库(NSPL)- 功能原语工具箱等

维护者

详细信息

github.com/ihor/Nspl

源代码

问题

1.3 2019-03-21 20:38 UTC

This package is auto-updated.

Last update: 2024-08-29 04:14:02 UTC


README

非标准 PHP 库(NSPL)是一组旨在解决日常常见问题的模块集合

  • nspl\f - 提供对其他函数操作的函数。有助于以函数式编程范式编写代码
  • nspl\op - 提供执行标准 PHP 操作的函数,可以作为回调传递给高阶函数。模仿 Python 的 operator 模块
  • nspl\a - 提供缺失的数组函数,也可以应用于可遍历序列
  • nspl\a\lazy - 提供 \nspl\a 中函数的延迟版本
  • nspl\args - 验证函数参数(将在 2.0 版本中移入单独的包)
  • nspl\ds - 提供非标准的数据结构及其操作方法
  • nspl\rnd - 帮助从数据序列中随机选择项

NSPL 旨在使代码更加紧凑、更简洁,但仍然清晰易读。请看以下示例

// get user ids
$userIds = map(propertyGetter('id'), $users);

// or sort them by age
$sortedByAge = sorted($users, methodCaller('getAge'));

// or check if they all are online
$online = all($users, methodCaller('isOnline'));

// or define new function as composition of the existing ones
$flatMap = compose(rpartial(flatten, 1), map);

在纯 PHP 中,它将看起来像这样

// get user ids
$userIds = array_map(function($user) { return $user->id; }, $users);

// sort them by age, note that the following code modifies the original users array
usort($users, function($user1, $user2) {
    return $user1->getAge() - $user2->getAge();
});

// check if they all are online
$online = true;
foreach ($users as $user) {
    if (!$user->isOnline()) {
        $online = false;
        break;
    }
}

// define new function as composition of the existing ones
$flatMap = function($function, $list) {
    // note the inconsistency in array_map and array_reduce parameters
    return array_reduce(array_map($function, $list), 'array_merge', []);
};

您可以在下面的 库参考这里 找到更多示例。

安装

使用 composer

在您的 composer.json 文件中定义以下要求

"require": {
    "ihor/nspl": "~1.3"
}

或者在命令行中执行以下操作

composer require ihor/nspl

对于包含更多功能的最新版本,需要版本 2.0.*-dev

手动

检出 代码 并包含 autoload.php

include 'path/to/nspl/autoload.php';

参考

这是针对开发版本 2.0.*-dev 的文档,其中包含最新的更改。对于版本 1.3(最新稳定版本)的文档,请点击 这里

在此,我假设使用 use function 导入了描述的函数

use function nspl\a\zip;
$pairs = zip([1, 2, 3], ['a', 'b', 'c']);

如果您的 PHP 版本小于 5.6,则应导入父命名空间并使用带有命名空间前缀的函数

use nspl\a;
$pairs = a\zip([1, 2, 3], ['a', 'b', 'c']);

目录

nspl\f

提供对其他函数操作的函数。有助于编写函数式编程风格的代码。

id($value)

恒等函数。返回传入的值。

assert(1 === id(1));
apply($function, array $args = [])

将给定的函数应用于参数并返回结果。

assert([1, 3, 5, 7, 9] === apply('range', [1, 10, 2]));
partial($function, $arg1)

返回一个新的部分函数,该函数将像 $function 一样行为,并预先将 参数传递给部分函数。

$sum = function($a, $b) { return $a + $b; };
$inc = partial($sum, 1);
rpartial($function, $arg1)

返回一个新的部分函数,该函数将像 $function 一样行为,并预先将 参数传递给 rpartial。

$cube = rpartial('pow', 3);
ppartial($function, array $args)

返回一个新的部分函数,该函数将像 $function 一样行为,并预先将 位置 参数传递给 ppartial。

$oddNumbers = ppartial('range', array(0 => 1, 2 => 2));
flipped($function)

返回一个接受反转顺序参数的函数。

compose($f, $g)

返回一个新的函数,该函数从右到左应用每个给定的函数到另一个函数的结果。例如 compose(f, g, h) 等同于 f(g(h(x)))

use const \nspl\a\flatten;
use const \nspl\a\map;
use function \nspl\f\compose;
use function \nspl\f\partial;
use function \nspl\f\rpartial;

$flatMap = compose(rpartial(flatten, 1), map);
assert(['hello', 'world', 'foo', 'bar'] === $flatMap(partial('explode', ' '), ['hello world', 'foo bar']));
pipe($input, $function1, $function2)

$input 传递给函数的组合(函数必须按相反顺序排列)。

use const \nspl\op\sum;
use const \nspl\a\filter;
use const \nspl\a\map;
use const \nspl\a\reduce;
use function \nspl\f\partial;

$isEven = function($x) { return $x % 2 === 0; };
$square = function($x) { return $x * $x; };

// sum of squares of all even numbers less than 20
$sum = pipe(
    range(1, 20),
    partial(filter, $isEven),
    partial(map, $square),
    partial(reduce, sum)
);

提示

您可以使用 链式调用 来消除序列变换中的部分函数。

use function \nspl\a\with;

$sum = with(range(1, 20))
   ->filter($isEven)
   ->map($square)
   ->reduce(sum);
curried($function, $withOptionalArgs = false)

返回函数的 柯里化 版本。如果您打算柯里化一个使用 func_get_args() 读取参数的函数,则将参数数量作为第二个参数传递。

如果第二个参数为 true,则使用可选参数柯里化函数;否则,只使用必需参数柯里化。或者,您可以传递要柯里化的确切参数数量。

uncurried($function)

返回 柯里化函数 的正常(非柯里化)版本。

memoized($function)

返回缓存结果的 memoized 版本的 $function,当相同的输入再次出现时。

$f = function($arg) {
    echo sprintf("Performing heavy calculations with '%s'\n", $arg);
    return $arg;
};

$memoized = memoized($f);
echo $memoized('Hello world!') . "\n";
echo $memoized('Hello world!') . "\n";

输出

Performing heavy calculations with 'Hello world!'
Hello world!
Hello world!
throttled($function, $wait)

返回传递函数的节流版本,当重复调用时,实际上最多每 wait 毫秒调用一次原始函数。

$f = function() {
    echo "Invoked\n";
};

$throttled = throttled($f, 10);

$startedAt = microtime(true);
do {
    $throttled();
} while((microtime(true) - $startedAt) * 1000 < 30); // 30ms

输出

Invoked
Invoked
Invoked
回调

nspl\f 在其常量中提供所有其函数作为回调,这些常量与函数具有相同的名称。

use const \nspl\a\map;
use const \nspl\a\filter;

$incListItems = partial(map, function($v) { return $v + 1; });
$filterNumbers = partial(filter, 'is_numeric');

查看更多 \nspl\f 示例 这里

nspl\op

nspl\op 提供执行标准 PHP 操作的函数,可以将它们作为回调传递给高阶函数。模拟 Python 的 operator 模块。例如

use const nspl\op\sum;
use function nspl\a\reduce;

assert(6 === reduce(sum, [1, 2, 3]));
回调

模块提供以下操作,既是函数又是回调。下面是一个示例。

itemGetter($key)

返回一个函数,该函数返回给定数组的键值。

use function nspl\op\itemGetter;
use function nspl\a\map;

assert([2, 5, 8] === map(itemGetter(1), [[1, 2, 3], [4, 5, 6], [7, 8, 9]]));
propertyGetter($property)

返回一个函数,该函数返回给定对象的属性值。

$userIds = map(propertyGetter('id'), $users);
methodCaller($method, array $args = array())

返回一个函数,该函数返回给定对象在预定义参数上的方法结果。

$userIds = map(methodCaller('getId'), $users);
instanceCreator($class)

返回一个函数,该函数返回一个预定义类的新实例,将参数传递给构造函数。

$users = map(instanceCreator(User::class), $usersData);

查看更多 \nspl\op 示例 这里

nspl\a

提供缺失的数组函数,也可以应用于可遍历序列。

all($sequence, $predicate)

如果序列中的所有项都满足谓词(或如果序列为空),则返回 true。如果没有传递谓词,则如果序列中的所有项都为真,则返回 true。

assert(true === all([true, true, true]));
any($sequence, $predicate)

如果序列中的任何项满足谓词,则返回 true。如果没有传递谓词,则如果序列中的任何项为真,则返回 true。

assert(true === any([true, false, false]));
map($function, $sequence)

将一个只有一个参数的函数应用到序列的每个项上

assert(['A', 'B', 'C'] === map('strtoupper', ['a', 'b', 'c']));
flatMap($function, $sequence)

将一个只有一个参数的函数应用到序列的每个项上,并展平结果

$duplicate = function($v) { return [$v, $v]; }
assert(['hello', 'hello', 'world', 'world'] === flatMap($duplicate, ['hello', 'world']));
zip($sequence1, $sequence2)

连接两个或多个序列

assert([[1, 'a'], [2, 'b'], [3, 'c']] === zip([1, 2, 3], ['a', 'b', 'c']));
zipWith($function, $sequence1, $sequence2)

通过将作为第一个参数给出的函数进行连接来泛化 zip

use const \nspl\op\sum;

assert([101, 1002, 10003] === zipWith(sum, [1, 2, 3], [100, 1000, 10000]));
reduce($function, $sequence, $initial = 0)

将一个有两个参数的函数累积应用到序列项上,从左到右将序列减少到单个值

assert(6 === reduce(function($a, $b) { return $a + $b; }, [1, 2, 3]));

// Which is the same as
use const \nspl\op\sum;
assert(6 === reduce(sum, [1, 2, 3]));
filter($predicate, $sequence)

返回满足谓词的序列项

assert([1, 2, 3] === filter('is_numeric', ['a', 1, 'b', 2, 'c', 3]));
filterNot($predicate, $sequence)

返回不满足谓词的序列项

assert(['a', 'b', 'c'] === filterNot('is_numeric', ['a', 1, 'b', 2, 'c', 3]));
take($sequence, $N, $step = 1)

返回具有给定步长的第一个 N 个序列项

assert([1, 3, 5] === take([1, 2, 3, 4, 5, 6, 7, 8, 9], 3, 2));
takeKeys($sequence, array $keys)

返回仅包含给定键的序列

assert(array('hello' => 1, 'world' => 2) === takeKeys(array('hello' => 1, 'world' => 2, 'foo' => 3), ['hello', 'world']));
takeWhile($predicate, $sequence)

返回所有满足谓词的项的最长序列前缀

assert([1, 2, 3] === takeWhile('is_numeric', [1, 2, 3, 'a', 'b', 'c', 4, 5, 6]));
first($sequence)

返回序列的第一个项

assert(1 === first([1, 2, 3, 4, 5, 6, 7, 8, 9]));
second($sequence)

返回序列的第二个项

assert(2 === second([1, 2, 3, 4, 5, 6, 7, 8, 9]));
drop($sequence, $N)

删除第一个 N 个序列项

assert([7, 8, 9] === drop([1, 2, 3, 4, 5, 6, 7, 8, 9], 6));
dropKeys($sequence, array $keys)

返回包含所有键但不包含给定键的数组

assert(array('hello' => 1, 'world' => 2) === dropKeys(array('hello' => 1, 'world' => 2, 'foo' => 3), ['foo']));
dropWhile($predicate, $sequence)

删除所有满足谓词的项的最长序列前缀

assert(['a', 'b', 'c', 4, 5, 6] === dropWhile('is_numeric', [1, 2, 3, 'a', 'b', 'c', 4, 5, 6]));
last($sequence)

返回序列的最后一个项

assert(9 === last([1, 2, 3, 4, 5, 6, 7, 8, 9]));
partition($predicate, $sequence)

返回两个列表,一个包含谓词返回 true 的值,另一个包含返回 false 的项

assert([[1, 2, 3], ['a', 'b', 'c']] === partition('is_numeric', ['a', 1, 'b', 2, 'c', 3]));
span($predicate, $sequence)

返回两个列表,一个包含谓词返回 true 直到谓词返回 false 的值,另一个包含所有留下的项

assert([[1], ['a', 2, 'b', 3, 'c']] === span('is_numeric', [1, 'a', 2, 'b', 3, 'c']));
indexed($sequence, $by, $keepLast = true, $transform = null)

返回包含索引序列项的数组

$by 是一个数组键或一个函数 如果 $keepLast 为 true,则仅返回具有键的最后项,否则返回具有相同键值的项的列表 $transform 是一个函数,用于在索引后转换列表项

$indexedById = indexed([
    array('id' => 1, 'name' => 'John'),
    array('id' => 2, 'name' => 'Kate'),
    array('id' => 3, 'name' => 'Robert'),
], 'id');
sorted($sequence, $reversed = false, $key = null, $cmp = null)

返回包含传递的序列的排序项的数组

如果 $reversed 为 true,则返回反转排序的序列。如果 $reversed 不是布尔值且未传递 $key,则作为 $key 参数处理 $key 是一个只有一个参数的函数,用于从每个项中提取比较键 $cmp 是一个有两个参数的函数,根据第一个参数是否小于、等于或大于第二个参数返回负数、零或正数

assert([1, 2, 3] === sorted([2, 3, 1]));
assert(['c', 'b', 'a'] === sorted(['c', 'a', 'b'], true));

$usersSortedByName = sorted($users, function($u) { return $u->getName(); });

// Which is the same as
use function \nspl\op\methodCaller;
$usersSortedByName = sorted($users, methodCaller('getName'));

查看更多 \nspl\a\sorted 示例 这里

keySorted($sequence, $reversed = false)

返回按键排序的序列项的数组

assert(array('a' => 1, 'b' => 2, 'c' => 3) === keySorted(array('b' => 2, 'c' => 3, 'a' => 1));
flatten($sequence, $depth = null)

展平多维序列

assert([1, 2, 3, 4, 5, 6, 7, 8, 9] === flatten([[1, [2, [3]]], [[[4, 5, 6]]], 7, 8, [9]]));
assert([1, 2, [3], [4, 5, 6], 7, 8, 9] === flatten([[1, [2, [3]]], [[[4, 5, 6]]], 7, 8, [9]], 2));
pairs($sequence, $valueKey = false)

返回一个包含 (键,值) 对的列表。如果 $valueKey 为真,则返回 (值,键) 对。

assert([['a', 'hello'], ['b', 'world'], ['c', 42]] === pairs(array('a' => 'hello', 'b' => 'world', 'c' => 42)));
merge($sequence1, $sequence2)

返回包含 $sequence1 项和 $sequence2 项的数组

assert([1, 2, 3, 4, 5, 6] === merge([1, 2, 3], [4, 5, 6]));
reorder(array $list, $from, $to)

将列表项移动到另一个位置

assert([2, 0, 1] === reorder([0, 1, 2], 2, 0)); // move item from the 2nd position to the begining of the list
value($array, $key, $default = null)

根据键返回数组值,如果存在则返回默认值

$data = array('a' => 1, 'b' => 2, 'c' => 3);
assert(2 === value($data, 'b', -1));
assert(-1 === value($data, 'd', -1));
values($sequence)

返回序列值的列表

assert([1, 2, 3] === values(array('a' => 1, 'b' => 2, 'c' => 3)));
keys($sequence)

返回序列键的列表

assert(['a', 'b', 'c'] === keys(array('a' => 1, 'b' => 2, 'c' => 3)));
in($item, $sequence)

检查项目是否存在于数组或可遍历对象中

assert(true === in(1, [1, 2, 3]);
diff($sequence1, $sequence2)

计算数组的差集或可遍历对象的差集

assert([1] === diff([1, 2, 3], new ArrayObject([2, 3, 4]));
intersect($sequence1, $sequence2)

计算数组或可遍历对象的交集

assert([2, 3] === intersect([1, 2, 3], new ArrayObject([2, 3, 4]));
cartesianProduct($sequences)

计算两个或多个数组或可遍历对象的笛卡尔积

assert([
    [1, 'a'],
    [1, 'b'],
    [2, 'a'],
    [2, 'b'],
], cartesianProduct([1, 2], ['a', 'b']));
assert([
    array('hello' => 1, 'world' => 'a'),
    array('hello' => 1, 'world' => 'b'),
    array('hello' => 2, 'world' => 'a'),
    array('hello' => 2, 'world' => 'b'),
], cartesianProduct(array('hello' => [1, 2], 'world' => ['a', 'b'])));
isList($var)

如果变量是列表,则返回true

链式调用

可以使用with函数链式调用数组函数

use function nspl\op\sum;

$square = function($n) { return $n * $n; };

$isEven = function($n) { return $n % 2 === 0; };

$sum = with(range(1, 5))
  ->filter($isEven)
  ->map($square)
  ->reduce(sum);

assert(20 === $sum);
回调

nspl\a在其常量中提供了所有其函数作为回调,这些常量的名称与函数相同。

use const \nspl\a\first;
assert([1, 2, 3] === map(first, [[1, 'a'], [2, 'b'], [3, 'c']]));

查看更多\nspl\a示例这里

nspl\lazy

提供来自nspl\a的函数的懒加载版本

当您不需要处理数组或任何其他可遍历序列的所有值时,此模块可能很有用。要了解这些懒加载函数是如何工作的,请看以下示例。

让我们定义一个函数,该函数包装一个生成器函数并记录它产生的所有值。这将帮助我们了解函数调用的顺序

// Calls generator function and logs the yielded values
function logged(callable $generatorFunction)
{
    static $count = 1;
    return function(...$args) use ($generatorFunction, &$count) {
        foreach ($generatorFunction(...$args) as $value) {
            echo $count++ . '. ' .  (string) $generatorFunction . ' -> ' . $value . "\n";
            yield $value;
        };
    };
}

为了有一些要操作的数据,让我们定义一个函数,该函数返回所有自然数。由于它返回所有自然数,所以它永远不会终止

function naturalNumbers()
{
    $current = 1;
    while (true) yield $current++;
}
const naturalNumbers = 'naturalNumbers';

此外,让我们定义我们想要对这些数字执行的操作

// Returns square of a number
function square($n)
{
    return $n * $n;
}
const square = 'square';

// Checks if a number is even
function isEven($n)
{
    return $n % 2 === 0;
}
const isEven = 'isEven';

现在让我们假设我们想要取前三个偶数自然数并计算它们的平方

use const nspl\a\lazy\{take, map, filter};

$map = logged(map);
$take = logged(take);
$filter = logged(filter);
$numbers = logged(naturalNumbers)();

$evenNumbers = $filter(isEven, $numbers); // filter only even numbers
$firstThreeEvenNumbers = $take($evenNumbers, 3); // take only first 3 even numbers
$result = $map(square, $firstThreeEvenNumbers); // and calculate their squares

foreach ($result as $value) {
    echo "\nNext value is $value \n\n";
}

当我们运行此示例时,我们将看到以下输出

1. naturalNumbers -> 1
2. naturalNumbers -> 2
3. \nspl\a\lazy\filter -> 2
4. \nspl\a\lazy\take -> 2
5. \nspl\a\lazy\map -> 4

Next value is 4

6. naturalNumbers -> 3
7. naturalNumbers -> 4
8. \nspl\a\lazy\filter -> 4
9. \nspl\a\lazy\take -> 4
10. \nspl\a\lazy\map -> 16

Next value is 16

11. naturalNumbers -> 5
12. naturalNumbers -> 6
13. \nspl\a\lazy\filter -> 6
14. \nspl\a\lazy\take -> 6
15. \nspl\a\lazy\map -> 36

Next value is 36

如果我们使用常规的非懒加载版本这些函数,我们将生成所有自然数,然后过滤出偶数,然后只取前三个,然后计算它们的平方。相反,您可以看到函数是依次调用的,将结果传递给下一个函数,直到我们完成整个循环

  1. 我们取第一个自然数 – 1。它不是偶数,所以我们跳过了它
  2. 我们取下一个 – 2,它是偶数
  3. 所以它通过了filter函数
  4. 它是我们取的第一个数字,所以它也通过了take函数
  5. 然后我们计算它的平方并打印结果

相同的操作在步骤6-10和11-15中重复。在步骤14中,take函数取了最后一个第三个数字。因此,在步骤15之后,当map请求下一个值时,take没有产生任何内容,整个迭代完成。

查看此示例这里

可以重写上面的代码以使用链式调用

$result = with(naturalNumbers())
    ->filter(isEven)
    ->take(3)
    ->map(square);

提示

请注意,虽然\nspl\a\lazy中的函数允许您避免重复计算,但在需要处理所有序列值的情况下,\nspl\a中的函数将更快地完成工作。

nspl\args

帮助验证函数参数

expects($constraints, $arg, $atPosition = null, $otherwiseThrow = '\InvalidArgumentException')

检查参数是否满足所需的约束,如果不满足则抛出相应的异常。

$constraints是可调用的,如果参数满足要求则返回true;它也可能包含所需的类名。如果$atPosition为null,则自动计算位置,将给定的参数与传递给函数的实际参数进行比较。$otherwiseThrow定义了如果给定的参数无效则抛出的异常,可以是异常类或异常对象

use const \nspl\args\int;
use const \nspl\args\string;
use const \nspl\args\arrayAccess;
use function \nspl\args\expects;

function nth($sequence, $n)
{
    expects([arrayAccess, string], $sequence);
    expects(int, $n);

    return $sequence[$n];
}

nth('hello world', 'blah');

输出

InvalidArgumentException: Argument 2 passed to nth() must be integer, string 'blah' given in /path/to/example.php on line 17

Call Stack:
    0.0002     230304   1. {main}() /path/to/example.php:0
    0.0023     556800   2. sqr() /path/to/example.php:17
expectsAll($constraints, array $args, array $atPositions = [], $otherwiseThrow = '\InvalidArgumentException')

检查所有指定的参数是否满足所需的约束,否则抛出相应的异常。

use const \nspl\args\numeric;
use function \nspl\args\expects;

function sum($x, $y)
{
    expectsAll(numeric, [$x, $y]);

    return $x + $y;
}
expectsOptional($constraints, $arg, $atPosition = null, $otherwiseThrow = '\InvalidArgumentException')

检查参数是否为null或满足所需的约束,否则抛出相应的异常。

function splitBy($string, $separator = ' ', $limit = null)
{
    expectsAll(string, [$string, $separator]);
    expectsOptional(int, $limit);

    return explode($separator, $string, $limit);
}
预定义约束

该模块提供预定义的约束。可以是以下两种类型之一

  • OR约束,使用or运算符进行评估(例如,expects([int, string], $arg)评估为$arg必须是intstring
  • AND约束,使用and运算符进行评估(例如,expects([string, longerThan(3), shorterThan(10)], $arg)评估为$arg必须是长度大于3且小于10的字符串)。如果您想将多个AND约束评估为OR约束,可以使用any约束。如果您想将多个OR约束评估为AND约束,可以使用all约束
function setUsername($username)
{
    expects([string, longerThan(3), shorterThan(10)], $username);
    // ...
}

function setState($state)
{
    expects(values('running', 'idle', 'stopped'), $state);
    // ...
}

Duck-typing示例

class Service
{
    // ...
    public function setCache($cache)
    {
        expects(withMethods('set', 'get'), $cache);
        $this->cache = $cache;
    }
    // ....
}
自定义约束

可以使用自定义约束。只需定义一个新函数,当参数满足约束时返回true

function even($value)
{
    return is_int($value) && $value %2 === 0;
}

function half($number)
{
    expects('even', $number);
    return $number / 2;
}

或者,我们可以通过引入一个常量使其更方便使用

const even = 'even';

function half($number)
{
    expects(even, $number);
    return $number / 2;
}

half('pie');

输出

InvalidArgumentException: Argument 1 passed to half() must be even, string 'pie' given in /path/to/example.php on line 25

Call Stack:
    0.0009     253640   1. {main}() /path/to/example.php:0
    0.0123     673984   2. half() /path/to/example.php:25

如果您需要创建一个接受参数的约束,您必须创建一个实现\nspl\args\Constraint接口的可调用对象。它包含两个方法

  • __invoke($value) - 如果值满足约束则返回true
  • __toString() - 返回文本,该文本将在值不满足约束时用作异常。文本必须包含一个消息,该消息位于异常消息中的"must"之后。

nspl\ds

提供非标准数据结构和与之相关的方法

默认数组

具有默认值的数组,对于缺少的键。如果您传递一个函数作为默认值,则将无参数调用该函数以提供给定键的默认值,此值将插入到数组中,并为该键返回。使用DefaultArray将此代码

$a = array();
foreach([1, 2, 1, 1, 3, 3, 3] as $v) {
    if (!isset($a[$v])) {
        $a[$v] = 0;
    }
    ++$a[$v];
}

转换为

$a = defaultarray(0);
foreach([1, 2, 1, 1, 3, 3, 3] as $v) {
    ++$a[$v];
}
defaultarray($default, $data = array())

返回新的DefaultArray

集合

一个不包含重复元素的类似数组的集合。它支持基本集合操作,这些操作接受其他集合、数组和可遍历对象作为参数

$set = set(1, 2);

$set->add('hello');
$set[] = 'world';

$set->delete('hello');

$array = [1, 2, 3];
$intersection = $set->intersection($array);

$anotherSet = Set::fromArray([1, 2, 3]);
$difference = $set->difference($anotherSet);

$iterator = new \ArrayIterator([1, 2, 3]);
$union = $set->union($iterator);

$isSubset = $set->isSubset([1, 2, 'hello', 'world']);

$isSuperset = $set->isSuperset([1, 2]);
集合

返回新的Set

在此处检查更多\nspl\ds示例 这里

nspl\rnd

randomString($length)

返回给定长度的随机字母数字字符串

choice($sequence)

从非空序列中返回一个随机项

weightedChoice($weightPairs)

从带有关联权重(作为项和权重的对)的非空项序列中返回一个随机项

use function \nspl\rnd\weightedChoice;
use function \nspl\a\pairs;

$nextPet = weightedChoice([['cat', 20], ['hamster', 30], ['dog', 50]]);
$nextFavouriteColor = weightedChoice(pairs(array(
    'red' => 0.2,
    'green' => 0.3,
    'blue' => 0.5,
)));
sample($population, $length, $preserveKeys = false)

返回从人口序列中选择的k长度列表的唯一项

在此处检查更多\nspl\rnd示例 这里

nspl

getType($var)

返回变量的类型或其对象的类名

路线图

  • 使用PHP 7.2的最新功能重写库
  • nspl\args移动到单独的模块

贡献

此项目使用语义版本标记版本。请将您的拉取请求提交到引入问题的最新发布分支。

反馈

目前还没有邮件列表或讨论组。请使用GitHub问题、拉取请求或关注我的Twitter @IhorBurlachenko