dusank / knapsack
PHP 的集合库
Requires
- php: >=5.6.0
Requires (Dev)
- ciaranmcnulty/phpspec-typehintedmethods: ^1.0
- henrikbjorn/phpspec-code-coverage: ^2.0
- phpmd/phpmd: ^2.0
- phpspec/phpspec: ^2.0
- phpunit/phpunit: ^5.0
- squizlabs/php_codesniffer: ^2.0
- symfony/console: ^2.7
README
PHP 的集合管道库
Knapsack 是一个 PHP >= 5.6 的集合库,实现了 Clojure 序列的大部分操作,并增加了一些额外的操作。所有功能都作为函数(用于函数式编程)和集合管道对象方法提供。
Knapsack 的核心是其 Collection 类。然而,它的每个方法都调用同名的简单函数,执行实际的繁重工作。这些函数位于 DusanKasan\Knapsack
命名空间中,您可以在 这里 找到它们。集合是一个 Traversable 实现(通过 IteratorAggregate),接受 Traversable 对象、数组或甚至作为构造函数参数的可调用对象,该对象产生 Traversable 对象或数组。它提供了大部分 Clojure 序列功能,并增加了一些额外的功能。它也是不可变的 - 对集合执行的操作将返回新的集合(或值),而不是修改原始集合。
大多数 Collection 的方法返回惰性集合(如 filter/map 等)。然而,一些返回非惰性集合(reverse)或简单值(count)。对于这些操作,必须遍历集合中的所有项目(并实现)。还有迭代某些集合项目但不影响/返回它们的操作(drop)。每个操作的行为以及惰性都会进行说明。
如果您想了解更多示例用法,请查看 规格 和/或 场景。还可以在您的机器上运行 性能测试,以查看此库的计算时间影响(以下包括输出)。
请随时报告您发现的任何 问题。我将尽力尽快修复它们,但欢迎社区 pull requests 修复它们。
文档
请查看文档(这是本说明书的整理版本),网址为 http://dusankasan.github.io/Knapsack
安装
使用 Composer 需要此包。
composer require dusank/knapsack
用法
通过静态或动态构造函数实例化
use DusanKasan\Knapsack\Collection; $collection1 = new Collection([1, 2, 3]); $collection2 = Collection::from([1, 2, 3]); //preferred since you can call methods on its result directly.
使用数组、Traversable 对象或产生 Traversables 的可调用对象
$collection1 = Collection::from([1, 2, 3]); $collection2 = Collection::from(new ArrayIterator([1, 2, 3]); //Used because Generator can not be rewound $collection2 = Collection::from(function() { //must have 0 arguments foreach ([1, 2, 3] as $value) { yield $value; } });
基本的 map/reduce
$result = Collection::from([1, 2]) ->map(function($v) {return $v*2;}) ->reduce(function($tmp, $v) {return $tmp+$v;}, 0); echo $result; //6
使用 Knapsack 的集合函数进行相同的 map/reduce
$result = reduce( map( [1, 2], function($v) {return $v*2;} ), function($tmp, $v) {return $tmp+$v;}, 0 ); echo $result; //6
获取斐波那契序列的前 5 个项
$result = Collection::iterate([1,1], function($v) { return [$v[1], $v[0] + $v[1]]; //[1, 2], [2, 3] ... }) ->map('\DusanKasan\Knapsack\first') //one of the collection functions ->take(5); foreach ($result as $item) { echo $item . PHP_EOL; } //1 //1 //2 //3 //5
如果从返回集合中项的函数返回数组或可遍历对象,可以使用可选标志将其转换为集合。默认情况下,它以原样返回项。
$result = Collection::from([[[1]]]) ->first(true) ->first(); var_dump($result); //[1]
集合是不可变的
function multiplyBy2($v) { return $v * 2; } function multiplyBy3($v) { return $v * 3; } function add($a, $b) { return $a + $b; } $collection = Collection::from([1, 2]); $result = $collection ->map('multiplyBy2') ->reduce(0, 'add'); echo $result; //6 //On the same collection $differentResult = $collection ->map('multiplyBy3') ->reduce(0, 'add'); echo $differentResult; //9
键不是设计时唯一的
这会影响性能。只有当你需要调用 toArray() 时,这个问题才会出现。在这种情况下,你应该在之前调用 values()。
$result = Collection::from([1, 2])->concat([3,4]); //arrays have unique keys $result->toArray(); //[3,4] $result->values()->toArray(); //[1, 2, 3, 4] //When iterating, you can have multiple keys. foreach ($result as $key => $item) { echo $key . ':' . $item . PHP_EOL; } //0:1 //1:2 //0:3 //1:4
提供了 Collection 特性
如果你希望在现有的类中直接使用所有 Collection 方法,无需代理它们的调用,可以直接使用提供的 CollectionTrait。默认情况下,这将适用于任何可遍历对象。在其他任何类中,你必须覆盖由特性提供的 getItems() 方法。请注意,在调用 filter 或任何其他返回集合的方法之后,返回的实际类型将是 Collection,而不是原始的可遍历对象。
class AwesomeIterator extends ArrayIterator { use CollectionTrait; } $iterator = new AwesomeIterator([1, 2, 3]); $iterator->size(); //3
性能测试
PHP 5.6
+------------------------------------------------------------------------------------+-----------------------+---------------------------+----------------------+ | operation details | native execution time | collection execution time | difference (percent) | +------------------------------------------------------------------------------------+-----------------------+---------------------------+----------------------+ | array_map vs Collection::map on 10000 integers (addition) | 0.0034945011138916s | 0.0034625053405762s | 99% | | array_map vs Collection::map on 10000 strings (concatenation) | 0.004361891746521s | 0.0049739360809326s | 114% | | array_map vs Collection::map on 10000 objects (object to field value) | 0.02332329750061s | 0.027161455154419s | 116% | | array_map vs Collection::map on 10000 md5 invocations | 0.0086771726608276s | 0.0080755949020386s | 93% | | array_map vs Collection::map on 10000 integers n, counting sum(0, n) the naive way | 1.5985415458679s | 1.580038356781s | 98% | +------------------------------------------------------------------------------------+-----------------------+---------------------------+----------------------+
PHP 7.1.1
+------------------------------------------------------------------------------------+-----------------------+---------------------------+----------------------+ | operation details | native execution time | collection execution time | difference (percent) | +------------------------------------------------------------------------------------+-----------------------+---------------------------+----------------------+ | array_map vs Collection::map on 10000 integers (addition) | 0.00082111358642578s | 0.001681661605835s | 204% | | array_map vs Collection::map on 10000 strings (concatenation) | 0.00081214904785156s | 0.0015116214752197s | 186% | | array_map vs Collection::map on 10000 objects (object to field value) | 0.0015491008758545s | 0.0036969423294067s | 238% | | array_map vs Collection::map on 10000 md5 invocations | 0.0032038688659668s | 0.0039427280426025s | 123% | | array_map vs Collection::map on 10000 integers n, counting sum(0, n) the naive way | 0.93844709396362s | 0.93354930877686s | 99% | +------------------------------------------------------------------------------------+-----------------------+---------------------------+----------------------+
构造函数
这些都是创建 Collection 类的方法。有一个默认构造函数和一些命名的(静态)构造函数。
new(iterable|callable $input)
默认构造函数接受数组、可遍历对象或无参数的 callable,该 callable 产生可遍历对象或数组。对于 callable 参数的使用案例是例如 Generator,它不能重置,因此 Collection 必须能够在重置自身时重建它。
$collection = new Collection([1, 2, 3]);
$collection = new Collection(new ArrayIterator([1, 2, 3]));
$generatorFactory = function () { foreach ([1, 2] as $value) { yield $value; } }; $collection = new Collection($generatorFactory);
from(iterable|callable $input)
Collection::from 是默认构造函数的静态别名。这是创建 Collection 的首选方式。
$collection = Collection::from([1, 2, 3]);
$collection = Collection::from(new ArrayIterator([1, 2, 3]));
$generatorFactory = function () { foreach ([1, 2] as $value) { yield $value; } }; $collection = Collection::from($generatorFactory);
iterate(mixed $input, callable $function)
返回一个惰性值集合,其中第一个值是 $input,所有后续值都是通过将 $function 应用到集合中的最后一个值来计算的。默认情况下,这会产生一个无限集合。然而,你可以通过抛出 NoMoreItems 异常来结束集合。
$collection = Collection::iterate(1, function ($value) {return $value + 1;}); // 1, 2, 3, 4 ...
repeat(mixed $value, int $times = -1)
返回一个惰性值集合,其中 $value 重复 $times 次。如果未提供 $times,则集合是无限的。
Collection::repeat(1); //infinite collection of ones
Collection::repeat(1, 4)->toArray(); //[1, 1, 1, 1]
range(int $start = 0, int $end = null, int step = 1)
返回一个惰性值集合,从 $start 开始,通过 $step 增量,直到达到 $end。
Collection::range(0, 6, 2)->toArray(); //[0, 2, 4, 6]
操作
这些是 Collection 类提供的操作(方法)。对于每个操作,Knapsack 命名空间中都有一个同名函数。该函数与方法的足迹相同,除了它有一个前置的额外参数 - 集合(数组或可遍历对象)。
标准迭代器方法
它实现了 https://php.ac.cn/manual/en/class.iterator.php
append(mixed $item, mixed $key = null) : Collection
返回一个惰性集合,其中包含此集合的项,并将 $item 添加为最后一个元素。如果未提供 $key,则其键将是序列中的下一个整数。
Collection::from([1, 3, 3, 2]) ->append(1) ->toArray(); //[1, 3, 3, 2, 1]
Collection::from([1, 3, 3, 2]) ->append(1, 'key') ->toArray(); //[1, 3, 3, 2, 'key' => 1]
toArray(append([1, 3, 3, 2], 1, 'key')); //[1, 3, 3, 2, 'key' => 1]
average() : int|float
返回此集合中值的平均值。
Collection::from([1, 2, 3, 2])->average(); //2 Collection::from([1, 2, 3, 2, 2])->average(); //2.2 Collection::from([])->average(); //0
average([1, 2, 3]); //2
combine(iterable $collection, bool $strict = false) : Collection
将此集合的值作为键,将 $collection 的值作为值组合。结果集合的长度等于较小集合的大小。如果 $strict 为 true,则两个集合的大小必须相等,否则抛出 ItemNotFound。当严格时,集合将立即实现。
Collection::from(['a', 'b']) ->combine([1, 2]) ->toArray(); //['a' => 1, 'b' => 2]
toArray(combine(['a', 'b'], [1, 2])); //['a' => 1, 'b' => 2]
concat(iterable ...$collections) : Collection
返回一个惰性集合,其中包含此集合的项,然后是第一个参数中的集合的项,然后是第二个,依此类推。
Collection::from([1, 3, 3, 2]) ->concat([4, 5]) //If we would convert to array here, we would loose 2 items because of same keys [4, 5, 3, 2] ->values() ->toArray(); //[1, 3, 3, 2, 4, 5]
toArray(values(concat([1, 3, 3, 2], [4, 5]))); //[1, 3, 3, 2, 4, 5]
contains(mixed $needle) : bool
如果 $needle 在集合中,则返回 true。
Collection::from([1, 3, 3, 2])->contains(2); //true
contains([1, 3, 3, 2], 2); //true
countBy(callable $function) : Collection
返回一个集合,其键是 $function(value, key) 的返回值,其值是此集合中返回此值的项的数量。
Collection::from([1, 2, 3, 4, 5]) ->countBy(function ($value) { return $value % 2 == 0 ? 'even' : 'odd'; }) ->toArray(); //['odd' => 3, 'even' => 2]
toArray(countBy([1, 2, 3, 4, 5], function ($value) {return $value % 2 == 0 ? 'even' : 'odd';}));
cycle() : Collection
返回一个无限惰性集合,其中包含此集合中的项无限重复。
Collection::from([1, 3, 3, 2]) ->cycle() ->take(8) //we take just 8 items, since this collection is infinite ->values() ->toArray(); //[1, 3, 3, 2, 1, 3, 3, 2]
toArray(values(take(cycle([1, 3, 3, 2]), 8))); //[1, 3, 3, 2, 1, 3, 3, 2]
diff(iterable ...$collections) : Collection
返回一个惰性集合,包含在 $collection 中但不在其他任何参数中的项,按第一个集合的键索引。注意 ...$collections 是非惰性迭代的。
Collection::from([1, 3, 3, 2]) ->diff([1, 3]) ->toArray(); //[3 => 2]
toArray(diff([1, 3, 3, 2], [1, 3])); //[3 => 2]
distinct() : Collection
返回一个惰性集合,包含不同的项。判断项是否在集合中的比较方式与 in_array 相同。
Collection::from([1, 3, 3, 2]) ->distinct() ->toArray(); //[1, 3, 3 => 2] - each item has key of the first occurrence
toArray(distinct([1, 3, 3, 2])); //[1, 3, 3 => 2] - each item has key of the first occurrence
drop(int $numberOfItems) : Collection
一种切片形式,返回除了前 $numberOfItems 项之外的所有项。
Collection::from([1, 2, 3, 4, 5]) ->drop(4) ->toArray(); //[4 => 5]
toArray(drop([1, 2, 3, 4, 5], 4)); //[4 => 5]
dropLast($numberOfItems = 1) : Collection
返回一个惰性集合,跳过最后 $numberOfItems 项。这些项仍然会被创建,只是被跳过了。
Collection::from([1, 2, 3]) ->dropLast() ->toArray(); //[1, 2]
Collection::from([1, 2, 3]) $collection ->dropLast(2) ->toArray(); //[1]
toArray(dropLast([1, 2, 3], 2)); //[1]
dropWhile(callable $function) : Collection
返回一个惰性集合,通过移除直到第一个 $function(value, key) 返回 false 的项。
Collection::from([1, 3, 3, 2]) ->dropWhile(function ($v) { return $v < 3; }) ->toArray(); //[1 => 3, 2 => 3, 3 => 2])
Collection::from([1, 3, 3, 2]) ->dropWhile(function ($v, $k) { return $k < 2 && $v < 3; }) ->toArray(); //[1 => 3, 2 => 3, 3 => 2])
Collection::from([1, 3, 3, 2]) ->dropWhile(function ($v, $k) { return $k < 2 && $v < 3; }) ->toArray(); //[1 => 3, 2 => 3, 3 => 2])
toArray(values(dropWhile([1, 3, 3, 2], function ($v) {return $v < 3;}))); // [3, 3, 2]
dump(int $maxItemsPerCollection = null, $maxDepth = null) : array
递归地将此集合转换为数组。
- 标量值按原样返回,
- 对于对象,返回类名 => 属性(name => value),只包含此类可访问的属性,
- 数组或可遍历对象返回为数组,
- 其他情况返回调用 gettype($input) 的结果
如果指定,$maxItemsPerCollection 将只留下指定的项目数量,如果原始集合更长,则在末尾追加一个新元素 '>>>'。
如果指定,$maxDepth 将只留下指定的 n 层嵌套,一旦达到最大嵌套级别,则将元素替换为 '^^^'。
如果遇到具有重复键的集合,则将重复的键(除第一个外)更改为格式 originalKey//duplicateCounter,其中 duplicateCounter 从第一个重复项开始为 1。所以 [0 => 1, 0 => 2] 将变为 [0 => 1, '0//1' => 2]
Collection::from([1, 3, 3, 2])->dump(); //[1, 3, 3, 2]
$collection = Collection::from( [ [ [1, [2], 3], ['a' => 'b'], new ArrayIterator([1, 2, 3]) ], [1, 2, 3], new ArrayIterator(['a', 'b', 'c']), true, new \DusanKasan\Knapsack\Tests\Helpers\Car('sedan', 5), \DusanKasan\Knapsack\concat([1], [1]) ] ); $collection->dump(2, 3); //[ // [ // [1, '^^^', '>>>'], // ['a' => 'b'], // '>>>' // ], // [1, 2, '>>>'], // '>>>' //] $collection->dump(); //[ // [ // [1, [2], 3], // ['a' => 'b'], // [1, 2, 3] // ], // [1, 2, 3], // ['a', 'b', 'c'], // true, // [ // 'DusanKasan\Knapsack\Tests\Helpers\Car' => [ // 'numberOfSeats' => 5, // ], // ], // [1, '0//1' => 1] //]
dump([1, 3, 3, 2], 2); // [1, 3, '>>>']
each(callable $function) : Collection
返回一个惰性集合,其中对每个项执行 $function(value, key)。
Collection::from([1, 2, 3, 4, 5]) ->each(function ($i) { echo $i . PHP_EOL; }) ->toArray(); //[1, 2, 3, 4, 5] //1 //2 //3 //4 //5
each([1, 2, 3, 4, 5], function ($v) {echo $v . PHP_EOL;}); //1 //2 //3 //4 //5
every(callable $function) : bool
如果 $function(value, key) 对此集合中的每个项都返回 true,则返回 true,否则返回 false。
Collection::from([1, 3, 3, 2]) ->every(function ($v) { return $v < 3; }); //false
Collection::from([1, 3, 3, 2]) ->every(function ($v, $k) { return $v < 4 && $k < 2; }); //false
every([1, 3, 3, 2], function ($v) {return $v < 5;}); //true
except(iterable $keys) : Collection
返回一个惰性集合,不包括与 $keys 中任何键关联的项。
Collection::from(['a' => 1, 'b' => 2]) ->except(['a']) ->toArray(); //['b' => 2]
toArray(except(['a' => 1, 'b' => 2], ['a'])); //['b' => 2]
extract(mixed $keyPath) : Collection
返回一个惰性集合,包含从 $collection 项中提取的数据,通过点分隔的键路径。支持 * 通配符。如果键包含 \ 或 *,则必须使用 \ 字符转义。
$collection = Collection::from([['a' => ['b' => 1]], ['a' => ['b' => 2]], ['c' => ['b' => 3]]]) $collection->extract('a.b')->toArray(); //[1, 2] $collection->extract('*.b')->toArray(); //[1, 2, 3]
toArray(extract([['a' => ['b' => 1]], ['a' => ['b' => 2]]], 'a.b')); //[1, 2]
filter(callable $function = null) : Collection
返回一个惰性集合,其中 $function(value, key) 返回 true 的项。
Collection::from([1, 3, 3, 2]) ->filter(function ($value) { return $value > 2; }) ->values() ->toArray(); //[3, 3]
Collection::from([1, 3, 3, 2]) ->filter(function ($value, $key) { return $value > 2 && $key > 1; }) ->toArray(); //[2 => 3]
toArray(values(filter([1, 3, 3, 2], function ($value) {return $value > 2;}))); //[3, 3]
如果没有提供 $function,则使用 \DusanKasan\Knapsack\identity,因此删除所有假值。
Collection::from([0, 0.0, false, null, "", []]) ->filter() ->isEmpty(); //true
isEmpty(values(filter([0, 0.0, false, null, "", []]))); //true
find(callable $function, mixed $ifNotFound = null, bool $convertToCollection = false) : mixed|Collection
返回 $function(value, key) 返回 true 的第一个值。如果没有匹配项,则返回 $ifNotFound。如果 $convertToCollection 为 true 且返回值是可迭代的,则返回 Collection 实例。
Collection::from([1, 3, 3, 2]) ->find(function ($value) { return $value < 3; }); //1
Collection::from([1, 3, 3, 2]) ->find(function ($value) { return $value > 3; }, 10); //10
Collection::from([1, 3, 3, 2]) ->find(function ($value, $key) { return $value < 3 && $key > 1; }); //2
//if the output can be converted to Collection (it's array or Traversable), it will be. Collection::from([1, [4, 5], 3, 2]) ->find(function ($value) { return is_array($value); }, [], true) ->size(); //2
find([1, 3, 3, 2], function ($value) {return $value > 2;}); //3
first(bool $convertToCollection = false) : mixed|Collection
返回集合中的第一个值或抛出 ItemNotFound 异常,如果集合为空。如果 $convertToCollection 为 true 且返回值是可迭代的,则返回 Collection 实例。
Collection::from([1, 2, 3])->first(); //1
Collection::from([[1], 2, 3])->first(); //[1]
Collection::from([])->first(); //throws ItemNotFound
first([1, 2, 3]); //1
flatten(int $depth = -1) : Collection
返回一个惰性集合,将一个或多个层的嵌套扁平化。如果没有传递 $depth 值,则删除所有嵌套。
Collection::from([1,[2, [3]]]) ->flatten() ->values() //1, 2 and 3 have all key 0 ->toArray(); //[1, 2, 3]
Collection::from([1,[2, [3]]]) ->flatten(1) ->values() //1, 2 and 3 have all key 0 ->toArray(); //[1, 2, [3]]
toArray(values(flatten([1, [2, [3]]]))); //[1, 2, 3]
flip() : Collection
返回一个惰性集合,其中键和值被反转。
Collection::from(['a' => 0, 'b' => 1]) ->flip() ->toArray(); //['a', 'b']
toArray(flip(['a' => 0, 'b' => 1])); //['a', 'b']
frequencies() : Collection
返回一个集合,其键是此集合中的不同项,其值是每个值的出现次数。
Collection::from([1, 3, 3, 2]) ->frequencies() ->toArray(); //[1 => 1, 3 => 2, 2 => 1]
toArray(frequencies([1, 3, 3, 2])); //[1 => 1, 3 => 2, 2 => 1]
get(mixed $key, bool $convertToCollection = false) : mixed|Collection
返回键 $key 对应的值。如果多个值具有此键,则返回第一个。如果没有值具有此键,则抛出 ItemNotFound
。如果 $convertToCollection 为 true 且返回值是可迭代的,则返回 Collection 实例。
Collection::from([1, 3, 3, 2])->get(2); //3
Collection::from([1, [1, 2]])->get(1, true)->toArray(); //[1, 2]
Collection::from([1, 3, 3, 2])->get(5); //throws ItemNotFound
get([1, 3, 3, 2], 2); //3
getOrDefault(mixed $key, mixed $default = null, bool $convertToCollection = false) : mixed|Collection
返回键 $key 对应的值。如果多个值具有此键,则返回第一个。如果没有值具有此键,则返回 $default。如果 $convertToCollection 为 true 且返回值是可迭代的,则返回 Collection 实例。
Collection::from([1, 3, 3, 2])->getOrDefault(2); //3
Collection::from([1, 3, 3, 2])->getOrDefault(5); //null
Collection::from([1, 3, 3, 2])->getOrDefault(5, 'asd'); //'asd'
Collection::from([1, 3, 3, 2])->getOrDefault(5, [1, 2], true)->toArray(); //[1, 2]
getOrDefault([1, 3, 3, 2], 5, 'asd'); //'asd'
groupBy(callable $function) : Collection
返回一个集合,其中项目根据 $function(value, key) 的返回值分组。
Collection::from([1, 2, 3, 4, 5]) ->groupBy(function ($value) { return $value % 2; }) ->toArray(); //[1 => [1, 3, 5], 0 => [2, 4]]
toArray(groupBy([1, 2, 3, 4, 5], function ($value) {return $value % 2;})); //[1 => [1, 3, 5], 0 => [2, 4]]
groupByKey(mixed $key) : Collection
返回一个集合,其中项目根据给定键的值分组。
Collection::from([ ['letter' => 'A', 'type' => 'caps'], ['letter' => 'a', 'type' => 'small'], ['letter' => 'B', 'type' => 'caps'], ]) ->groupByKey('type') ->map('DusanKasan\Knapsack\toArray') ->toArray(); // [ 'caps' => [['letter' => 'A', 'type' => 'caps'], ...], 'small' => [['letter' => 'a', 'type' => 'small']]]
$data = [ ['letter' => 'A', 'type' => 'caps'], ['letter' => 'a', 'type' => 'small'], ['letter' => 'B', 'type' => 'caps'], ]; toArray(map(groupByKey($data, 'type'), 'toArray')); //[ 'caps' => [['letter' => 'A', 'type' => 'caps'], ...], 'small' => [['letter' => 'a', 'type' => 'small']]]
has(mixed $key) : bool
检查此集合中是否存在 $key。
Collection::from(['a' => 1])->has('a'); //true
has(['a' => 1], 'a'); //true
indexBy(callable $function) : Collection
返回一个惰性集合,通过将每个项目的键从此集合的键改为 $function(value, key) 的结果来实现。
Collection::from([1, 3, 3, 2]) ->indexBy(function ($v) { return $v; }) ->toArray(); //[1 => 1, 3 => 3, 2 => 2]
toArray(indexBy([1, 3, 3, 2], '\DusanKasan\Knapsack\identity')); //[1 => 1, 3 => 3, 2 => 2]
interleave(iterable ...$collections) : Collection
返回一个惰性集合,包含来自第一个集合的第一个项目,来自第二个集合的第一个项目,第一个集合的第二个项目,依此类推。适用于任何数量的参数。
Collection::from([1, 3, 3, 2]) ->interleave(['a', 'b', 'c', 'd', 'e']) ->values() ->toArray(); //[1, 'a', 3, 'b', 3, 'c', 2, 'd', 'e']
toArray(interleave([1, 3, 3, 2], ['a', 'b', 'c', 'd', 'e'])); //[1, 'a', 3, 'b', 3, 'c', 2, 'd', 'e']
interpose(mixed $separator) : Collection
返回一个惰性集合,其中包含此集合的项目,由 $separator 项目分隔。
Collection::from([1, 2, 3]) ->interpose('a') ->values() // we must reset the keys, because each 'a' has undecided key ->toArray(); //[1, 'a', 2, 'a', 3]
toArray(interpose([1, 2, 3], 'a')); //[1, 'a', 2, 'a', 3]
intersect(iterable ...$collections) : Collection
返回一个惰性集合,包含在 $collection 中且在其他所有参数中存在的项目,按第一个集合的键索引。注意 ...$collections 是非惰性迭代的。
Collection::from([1, 2, 3]) ->intersect([1, 3]) ->toArray(); //[1, 2 => 3]
toArray(intersect([1, 2, 3],[1, 3])); //[1, 2 => 3]
isEmpty() : bool
如果集合为空,则返回 true。否则返回 false。
Collection::from([1, 3, 3, 2])->isEmpty(); //false
isEmpty([1]); //false
isNotEmpty() : bool
isEmpty 的相反。
Collection::from([1, 3, 3, 2])->isNotEmpty(); //true
isNotEmpty([1]); //true
keys() : Collection
返回一个惰性集合,包含此集合的键。
Collection::from(['a' => [1, 2], 'b' => [2, 3]]) ->keys() ->toArray(); //['a', 'b']
toArray(keys(['a' => [1, 2], 'b' => [2, 3]])); //['a', 'b']
last(bool $convertToCollection = false) : mixed|Collection
返回集合中的最后一个值,如果集合为空则抛出 ItemNotFound。如果 $convertToCollection 为 true 且返回值是可迭代的,则返回 Collection 实例。
Collection::from([1, 2, 3])->last(); //3
Collection::from([1, 2, [3]])->last(true)->toArray(); //[1]
Collection::from([])->last(); //throws ItemNotFound
last([1, 2, 3]); //3
map(callable $function) : Collection
返回一个集合,其中每个值都更改为执行 $function(value, key) 的输出。
Collection::from([1, 3, 3, 2]) ->map(function ($value) { return $value + 1; }) ->toArray(); //[2, 4, 4, 3]
toArray(map([1, 3, 3, 2], '\DusanKasan\Knapsack\increment')); //[2, 4, 4, 3]
mapcat(callable $mapper) : Collection
返回一个惰性集合,它是通过调用 map($mapper(value, key)) 然后展开 (1) 得到的。
Collection::from([1, 3, 3, 2]) ->mapcat(function ($value) { return [[$value]]; }) ->values() ->toArray(); //[[1], [3], [3], [2]]
Collection::from([1, 3, 3, 2]) ->mapcat(function ($key, $value) { return [[$key]]; }) ->values() ->toArray(); //[[0], [1], [2], [3]]
toArray(values(mapcat([1, 3, 3, 2], function ($value) {return [[$value]];}))); //[[1], [3], [3], [2]]
max() : mixed
返回此集合中的最大值。
Collection::from([1, 2, 3, 2])->max(); //3 Collection::from([])->max(); //null
max([1, 2, 3, 2]); //3
min() : mixed
返回此集合中的最小值。
Collection::from([1, 2, 3, 2])->min(); //1 Collection::from([])->min(); //null
min([1, 2, 3, 2]); //1
only(iterable $keys) : Collection
返回一个惰性集合,包含与 $keys 中的任何键关联的项目。
Collection::from(['a' => 1, 'b' => 2]) ->only(['b']) ->toArray(); //['b' => 2]
toArray(only(['a' => 1, 'b' => 2], ['b'])); //['b' => 2]
partition(int $numberOfItems, int $step = 0, iterable $padding = []) : Collection
返回一个惰性集合,其中包含 $numberOfItems 项的集合,每个集合间隔 $step 步。如果未提供 $step,则默认为 $numberOfItems,即分区不重叠。如果提供了 $padding 集合,则使用其元素(如果需要)来完成最后一个分区,直到 $numberOfItems 项。如果没有足够的填充元素,则返回一个包含少于 $numberOfItems 项的分区。
Collection::from([1, 3, 3, 2]) ->partition(3, 2, [0, 1]) ->toArray(); //[[1, 3, 3], [2 => 3, 3 => 2, 0 => 0]]
Collection::from([1, 3, 3, 2]) ->partition(3, 2) ->toArray(); //[[1, 3, 3], [2 => 3, 3 => 2]]
Collection::from([1, 3, 3, 2]) ->partition(3) ->toArray(); //[[1, 3, 3], [3 => 2]]
toArray(partition([1, 3, 3, 2], 3)); //[[1, 3, 3], [3 => 2]]
partitionBy(callable $function) : Collection
创建一个惰性集合,其中包含通过在 $function(value, key) 返回不同结果时对集合进行分区创建的集合。
Collection::from([1, 3, 3, 2]) ->partitionBy(function ($v) { return $v % 3 == 0; }) ->toArray(); //[[1], [1 => 3, 2 => 3], [3 => 2]]
toArray(partitionBy([1, 3, 3, 2], function ($value) {return $value % 3 == 0;})); //[[1], [1 => 3, 2 => 3], [3 => 2]]
prepend(mixed $item, mixed $key = null) : Collection
返回一个惰性集合,其中包含此集合的项目,并将 $item 添加为第一个元素。其键将为 $key。如果没有提供 $key,则其键将是下一个数值索引。
Collection::from([1, 3, 3, 2]) ->prepend(1) ->values() //both 1 have 0 key ->toArray(); //[1, 1, 3, 3, 2]
Collection::from([1, 3, 3, 2]) ->prepend(1, 'a') ->toArray(); //['a' => 1, 0 => 1, 1 => 3, 2 => 3, 3 => 2]
printDump(int $maxItemsPerCollection = null, $maxDepth = null) : Collection
调用 dump 在 $input 上,然后使用 var_export 打印它。返回集合。有关参数和输出文档,请参阅 dump 函数。
Collection::from([1, 3, 3, 2]) ->printDump() ->toArray(); //[1, 3, 3, 2]
toArray(printDump([1, 3, 3, 2])); //[1, 3, 3, 2]
realize() : Collection
实现集合 - 通过迭代它并将键/值存储起来将惰性集合转换为非惰性集合。
$helper->setValue(1); $realizedCollection = Collection::from([1, 3, 3, 2]) ->map(function ($item) use ($helper) {return $helper->getValue() + $item;}) ->realize(); $helper->setValue(10); $realizedCollection->toArray(); // [2, 4, 4, 3]
toArray(realize([1, 3, 3, 2])); //[1, 3, 3, 2]
reduce(callable $function, mixed $start, bool $convertToCollection = false) : mixed|Collection
通过遍历集合并调用$function(tmp, value, key),将集合减少到单个值,同时传递$start和当前键/项作为参数。可调用函数的输出用作下一次迭代的$start。可调用函数在最后一个元素上的输出是此函数的返回值。如果$convertToCollection为true且返回值是可迭代的,则返回Collection的实例。
Collection::from([1, 3, 3, 2]) ->reduce( function ($tmp, $i) { return $tmp + $i; }, 0 ); //9 Collection::from([1, 3, 3, 2]) ->reduce( function ($tmp, $i) { $tmp[] = $i + 1; return $tmp; }, [], true ) ->first(); //2
reduce([1, 3, 3, 2], function ($tmp, $value) {return $tmp + $value;}, 0); //9
reduceRight(callable $function, mixed $start, bool $convertToCollection = false) : mixed|Collection
与reduce类似,但从前一个元素到第一个元素遍历。如果$convertToCollection为true且返回值是可迭代的,则返回Collection的实例。
Collection::from([1, 3, 3, 2]) ->reduceRight( function ($tmp, $i) { return $tmp + $i; }, 0 ); //9 Collection::from([1, 3, 3, 2]) ->reduce( function ($tmp, $i) { $tmp[] = $i + 1; return $tmp; }, [], true ) ->first(); //3
reduceRight([1, 3, 3, 2], function ($tmp, $value) {return $tmp + $value;}, 0); //9
reductions(callable $reduction, mixed $start) : Collection
返回一个包含减少步骤的惰性集合。
Collection::from([1, 3, 3, 2]) ->reductions(function ($tmp, $i) { return $tmp + $i; }, 0) ->toArray(); //[1, 4, 7, 9]
toArray(reductions([1, 3, 3, 2], function ($tmp, $value) {return $tmp + $value;}, 0)); //[1, 4, 7, 9]
reject(callable $filter) : Collection
返回一个惰性集合,其中包含对$filter(value, key)返回false的项。
Collection::from([1, 3, 3, 2]) ->reject(function ($value) { return $value > 2; }) ->toArray(); //[1, 3 => 2]
Collection::from([1, 3, 3, 2]) ->reject(function ($value, $key) { return $value > 2 && $key > 1; }) ->toArray(); //[1, 1 => 3, 3 => 2]
toArray(reject([1, 3, 3, 2], function ($value) {return $value > 2;})); //[1, 1 => 3, 3 => 2]
replace(iterable $replacementMap) : Collection
返回一个惰性集合,其中与此集合中的任何键相等的项被替换为其值。
Collection::from([1, 3, 3, 2]) ->replace([3 => 'a']) ->toArray(); //[1, 'a', 'a', 2]
toArray(replace([1, 3, 3, 2], [3 => 'a'])); //[1, 'a', 'a', 2]
replaceByKeys(iterable $replacementMap) : Collection
返回一个惰性集合,其中包含来自$collection的项,但具有在$replacementMap键中找到的键的项被其值替换。
Collection::from([1, 3, 3, 2]) ->replace([3 => 'a']) ->toArray(); //[1, 3, 3, 'a']
toArray(replace([1, 3, 3, 2], [3 => 'a'])); //[1, 3, 3, 'a']
reverse() : Collection
返回一个非惰性集合,其中包含此集合中的项,但顺序相反。
Collection::from([1, 2, 3]) ->reverse() ->toArray(); //[2 => 3, 1 => 2, 0 => 1]
toArray(reverse([1, 2, 3])); //[2 => 3, 1 => 2, 0 => 1]
second(bool $convertToCollection = false) : mixed|Collection
返回$collection的第二个项,或者在$collection为空或只有一个项时抛出ItemNotFound。如果$convertToCollection为true且返回值是可迭代的,则将其转换为Collection。
Collection::from([1, 3, 3, 2])->second(); //3
second([1, 3]); //3
shuffle() : Collection
返回从此集合中随机排列的项的集合。
Collection::from([1, 3, 3, 2]) ->shuffle() ->toArray(); //something like [2 => 3, 0 => 1, 3 => 2, 1 => 3]
toArray(shuffle([1, 3, 3, 2])); //something like [2 => 3, 0 => 1, 3 => 2, 1 => 3]
size() : int
返回此集合中的项目数。
Collection::from([1, 3, 3, 2])->size(); //4
size([1, 3, 3, 2]); //4
sizeIsBetween(int $fromSize, int $toSize) : bool
检查此集合是否包含介于$fromSize到$toSize项之间。$toSize可以小于$fromSize。
Collection::from([1, 3, 3, 2])->sizeIsBetween(3, 5); //true
sizeIsBetween([1, 3, 3, 2], 3, 5); //true
sizeIs(int $size) : bool
检查此集合是否恰好有$size项。
Collection::from([1, 3, 3, 2])->sizeIs(4); //true
sizeIs([1, 3, 3, 2], 4); //true
sizeIsGreaterThan(int $size) : bool
检查此集合是否包含多于$size项。
Collection::from([1, 3, 3, 2])->sizeIsGreaterThan(3); //true
sizeIsGreaterThan([1, 3, 3, 2], 3); //true
sizeIsLessThan(int $size) : bool
检查此集合是否包含少于$size项。
Collection::from([1, 3, 3, 2])->sizeIsLessThan(5); //true
sizeIsLessThan([1, 3, 3, 2], 5); //true
slice(int $from, int $to) : Collection
返回一个惰性集合,其中包含从原始集合中的项目编号$from到项目编号$to的项(包括)。$from之前的项也被实现,只是没有返回。
Collection::from([1, 2, 3, 4, 5]) ->slice(2, 4) ->toArray(); //[2 => 3, 3 => 4]
Collection::from([1, 2, 3, 4, 5]) ->slice(4) ->toArray(); //[4 => 5]
toArray(slice([1, 2, 3, 4, 5], 4)); //[4 => 5]
some(callable $function) : bool
如果$function(value, key)为此集合中的至少一个项返回true,则返回true,否则返回false。
Collection::from([1, 3, 3, 2]) ->some(function ($value) { return $value < 3; }); //true
Collection::from([1, 3, 3, 2]) ->some(function ($value, $key) { return $value < 4 && $key < 2; }); //true
some([1, 3, 3 ,2], function ($value) {return $value < 3;}); //true
sort(callable $function) : Collection
使用$function(value1, value2, key1, key2)对集合进行排序。如果第一个参数被认为分别小于、等于或大于第二个参数,则$function应返回一个小于、等于或大于零的整数。
Collection::from([3, 1, 2]) ->sort(function ($a, $b) { return $a > $b; }) ->toArray(); //[1 => 1, 2 => 2, 0 => 3]
Collection::from([3, 1, 2]) ->sort(function ($v1, $v2, $k1, $k2) { return $v1 < $v2; }) ->toArray(); //[2 => 2, 1 => 1, 0 => 3]
toArray(sort([3, 1, 2], function ($a, $b) {return $a > $b;})); //[1 => 1, 2 => 2, 0 => 3]
splitAt(int $position) : Collection
返回一个包含惰性集合的集合:[take($position), drop($position)]。
Collection::from([1, 3, 3, 2]) ->splitAt(2) ->toArray(); //[[1, 3], [2 => 3, 3 => 2]]
toArray(splitAt([1, 3, 3, 2], 2)); //[[1, 3], [2 => 3, 3 => 2]]
splitWith(callable $function) : Collection
返回一个包含惰性集合的集合:[takeWhile($function(value, key)), dropWhile($function(value, key))]。
Collection::from([1, 3, 3, 2]) ->splitWith(function ($value) { return $value < 3; }) ->toArray(); //[[1], [1 => 3, 2 => 3, 3 => 2]]
Collection::from([1, 3, 3, 2]) ->splitWith(function ($value, $key) { return $key < 2 && $value < 3; }) ->toArray(); //[[1], [1 => 3, 2 => 3, 3 => 2]]
toArray(splitWith([1, 3, 3, 2], function ($value) {return $value < 3;})); //[[1], [1 => 3, 2 => 3, 3 => 2]]
sum() : int|float
返回此集合中所有值的总和。
Collection::from([1, 2, 3])->sum(); //6 Collection::from([1, 2, 3, 1.5])->sum(); //7.5 Collection::from([])->sum(); //0
sum([1, 2, 3]); //6
take(int $numberOfItems) : Collection
切片的一种形式,返回前$numberOfItems个项。
Collection::from([1, 2, 3, 4, 5]) ->take(2) ->toArray(); //[1, 2]
toArray(take([1, 2, 3, 4, 5], 2)); //[1, 2]
takeNth(int $step) : Collection
返回一个惰性集合,包含此集合中每隔第n个项。
Collection::from([1, 3, 3, 2]) ->takeNth(2) ->toArray(); //[1, 2 => 3]
toArray(takeNth([1, 3, 3, 2], 2)); //[1, 2 => 3]
takeWhile(callable $function) : Collection
返回一个惰性集合,从集合的开始到第一个对$function(value, key)返回false的项。
Collection::from([1, 3, 3, 2]) ->takeWhile(function ($value) { return $value < 3; }) ->toArray(); //[1]
Collection::from([1, 3, 3, 2]) ->takeWhile(function ($value, $key) { return $key < 2 && $value < 3; }) ->toArray(); //[1]
toArray(takeWhile([1, 3, 3, 2], function ($value) {return $value < 3;})); //[1]
transform(callable $transformer) : Collection
使用$transformer可调用函数对其自身进行操作,它接受一个集合并返回集合。这允许创建一个独立且可重用的算法。
$transformer = function (Collection $collection) { return $collection ->filter(function ($item) { return $item > 1; }) ->map('\DusanKasan\Knapsack\increment'); }; Collection::from([1, 3, 3, 2]) ->transform($transformer) ->toArray(); //[4, 4, 3]
toArray() : array
递归地将集合转换为数组。显然,这不是懒加载的,因为所有项都必须实现。内部调用 iterator_to_array。
Collection::from([1, 3, 3, 2])->toArray(); //[1, 3, 3, 2]
toArray([1, 3, 3, 2]); //[1, 3, 3, 2]
toString() : 字符串
通过将此集合的值连接成字符串返回一个字符串。
Collection::from([1, 'a', 3, null])->toString(); //'1a3' Collection::from([])->toString(); //''
toString([1, 'a', 3, null]); //'1a3'
transpose(iterable $collection) : 字符串
返回一个非懒加载的集合,通过交换每一行和对应的列。输入必须是多维集合,否则会抛出 InvalidArgumentException。
$arr = Collection::from([ new Collection([1, 2, 3]), new Collection([4, 5, new Collection(['foo', 'bar'])]), new Collection([7, 8, 9]), ])->transpose()->toArray(); // $arr = // [ // new Collection([1, 4, 7]), // new Collection([2, 5, 8]), // new Collection([3, new Collection(['foo', 'bar']), 9]), // ]
zip(iterable ...$collections) : 集合
返回一个非懒加载的集合,包含从此集合和每个传入集合的第n个位置的项。当任何集合在第n个位置没有项时停止。
Collection::from([1, 2, 3]) ->zip(['a' => 1, 'b' => 2, 'c' => 4]) ->map('\DusanKasan\Knapsack\toArray') ->toArray(); //[[1, 'a' => 1], [1 => 2, 'b' => 2], [2 => 3, 'c' => 4]] Collection::from([1, 2, 3]) ->zip(['a' => 1, 'b' => 2]) ->map('\DusanKasan\Knapsack\toArray') ->toArray(); //[[1, 'a' => 1], [1 => 2, 'b' => 2]]
toArray(map(zip([1, 2, 3], ['a' => 1, 'b' => 2, 'c' => 4]), '\DusanKasan\Knapsack\toArray')); //[[1, 'a' => 1], [1 => 2, 'b' => 2], [2 => 3, 'c' => 4]]
实用函数
这些是Knapsack附带的功能函数,可以帮助您在过渡到函数式编程时更轻松。
identity(mixed $value)
返回 $value
$value === identity($value); //true
compare(mixed $a, mixed $b)
默认比较函数。当 $a 逻辑上“小于”、“等于”或“大于” $b 时,返回一个负数、零或正数。
compare(1, 2); //-1
increment(int $value)
返回 $value 加一后的值。
increment(0) === 1; //true
decrement(int $value)
返回 $value 减一后的值。
decrement(2) === 1; //true