markrogoyski / itertools-php
PHP 迭代工具
Requires
- php: >=7.4.0
Requires (Dev)
- mikey179/vfsstream: ^1.6
- php-coveralls/php-coveralls: ^2.0
- php-parallel-lint/php-parallel-lint: ^1.3
- phploc/phploc: *
- phpmd/phpmd: ^2.10
- phpstan/phpstan: ^1.10
- phpunit/phpunit: ^9.0
- squizlabs/php_codesniffer: 3.*
- vimeo/psalm: ^5.11
This package is auto-updated.
Last update: 2024-08-28 04:31:36 UTC
README
IterTools - PHP 迭代工具,增强循环能力
受 Python 启发 - 为 PHP 设计。
特性
IterTools 通过提供两种类型的工具,让您成为迭代超级明星
- 循环迭代工具
- 流迭代工具
循环迭代工具示例
foreach (Multi::zip(['a', 'b'], [1, 2]) as [$letter, $number]) { print($letter . $number); // a1, b2 }
流迭代工具示例
$result = Stream::of([1, 1, 2, 2, 3, 4, 5]) ->distinct() // [1, 2, 3, 4, 5] ->map(fn ($x) => $x**2) // [1, 4, 9, 16, 25] ->filter(fn ($x) => $x < 10) // [1, 4, 9] ->toSum(); // 14
所有函数都适用于 iterable
集合
array
(类型)Generator
(类型)Iterator
(接口)Traversable
(接口)
README 文档已翻译成其他语言
快速参考
循环迭代工具
多重迭代
单次迭代
无限迭代
随机迭代
数学迭代
集合和多集迭代
排序迭代
文件迭代
转换迭代
总结
减少
流迭代工具
流源
流操作
流终端操作
总结终端操作
减少终端操作
转换终端操作
副作用终端操作
流调试操作
设置
将库添加到项目的 composer.json
文件中
{ "require": { "markrogoyski/itertools-php": "1.*" } }
使用 composer 安装库
$ php composer.phar install
Composer 会将 IterTools 安装在您的 vendor 文件夹中。然后您可以在 .php 文件中添加以下内容以使用库进行自动加载。
require_once __DIR__ . '/vendor/autoload.php';
或者,使用命令行中的 composer 来要求并安装 IterTools
$ php composer.phar require markrogoyski/itertools-php:1.*
最低要求
- PHP 7.4
用法
所有函数都适用于 iterable
集合
array
(类型)Generator
(类型)Iterator
(接口)Traversable
(接口)
多重迭代
链
将多个可迭代对象链接成一个连续的序列。
Multi::chain(iterable ...$iterables)
use IterTools\Multi; $prequels = ['Phantom Menace', 'Attack of the Clones', 'Revenge of the Sith']; $originals = ['A New Hope', 'Empire Strikes Back', 'Return of the Jedi']; foreach (Multi::chain($prequels, $originals) as $movie) { print($movie); } // 'Phantom Menace', 'Attack of the Clones', 'Revenge of the Sith', 'A New Hope', 'Empire Strikes Back', 'Return of the Jedi'
压缩
同时迭代多个可迭代集合。
Multi::zip(iterable ...$iterables)
use IterTools\Multi; $languages = ['PHP', 'Python', 'Java', 'Go']; $mascots = ['elephant', 'snake', 'bean', 'gopher']; foreach (Multi::zip($languages, $mascots) as [$language, $mascot]) { print("The {$language} language mascot is an {$mascot}."); } // The PHP language mascot is an elephant. // ...
压缩与多个可迭代输入一起工作--不仅限于两个。
$names = ['Ryu', 'Ken', 'Chun Li', 'Guile']; $countries = ['Japan', 'USA', 'China', 'USA']; $signatureMoves = ['hadouken', 'shoryuken', 'spinning bird kick', 'sonic boom']; foreach (Multi::zip($names, $countries, $signatureMoves) as [$name, $country, $signatureMove]) { $streetFighter = new StreetFighter($name, $country, $signatureMove); }
注意:对于长度不等的迭代,当最短的迭代器耗尽时停止迭代。
ZipEqual
同时迭代具有相等长度的多个可迭代集合。
如果长度不相等,将抛出 \LengthException
,这意味着至少一个迭代器在其他迭代器之前结束。
Multi::zipEqual(iterable ...$iterables)
use IterTools\Multi; $letters = ['A', 'B', 'C']; $numbers = [1, 2, 3]; foreach (Multi::zipEqual($letters, $numbers) as [$letter, $number]) { // ['A', 1], ['B', 2], ['C', 3] }
ZipFilled
同时迭代多个可迭代集合,如果长度不相等,则使用默认填充值。
Multi::zipFilled(mixed $filler, iterable ...$iterables)
use IterTools\Multi; $default = '?'; $letters = ['A', 'B']; $numbers = [1, 2, 3]; foreach (Multi::zipFilled($default, $letters, $numbers) as [$letter, $number]) { // ['A', 1], ['B', 2], ['?', 3] }
ZipLongest
同时迭代多个可迭代集合。
Multi::zipLongest(iterable ...$iterables)
对于长度不等的迭代,耗尽的迭代器将在剩余迭代中产生 null
。
use IterTools\Multi; $letters = ['A', 'B', 'C']; $numbers = [1, 2]; foreach (Multi::zipLongest($letters, $numbers) as [$letter, $number]) { // ['A', 1], ['B', 2], ['C', null] }
单次迭代
Chunkwise
以特定大小的块返回元素。
Single::chunkwise(iterable $data, int $chunkSize)
块大小必须至少为 1。
use IterTools\Single; $movies = [ 'Phantom Menace', 'Attack of the Clones', 'Revenge of the Sith', 'A New Hope', 'Empire Strikes Back', 'Return of the Jedi', 'The Force Awakens', 'The Last Jedi', 'The Rise of Skywalker' ]; foreach (Single::chunkwise($movies, 3) as $trilogy) { $trilogies[] = $trilogy; } // [ // ['Phantom Menace', 'Attack of the Clones', 'Revenge of the Sith'], // ['A New Hope', 'Empire Strikes Back', 'Return of the Jedi'], // ['The Force Awakens', 'The Last Jedi', 'The Rise of Skywalker]' // ]
Chunkwise Overlap
返回重叠的元素块。
Single::chunkwiseOverlap(iterable $data, int $chunkSize, int $overlapSize, bool $includeIncompleteTail = true)
- 块大小必须至少为 1。
- 重叠大小必须小于块大小。
use IterTools\Single; $numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]; foreach (Single::chunkwiseOverlap($numbers, 3, 1) as $chunk) { // [1, 2, 3], [3, 4, 5], [5, 6, 7], [7, 8, 9], [9, 10] }
Compress
通过过滤掉未选择的数据来压缩可迭代对象。
Single::compress(string $data, $selectors)
use IterTools\Single; $movies = [ 'Phantom Menace', 'Attack of the Clones', 'Revenge of the Sith', 'A New Hope', 'Empire Strikes Back', 'Return of the Jedi', 'The Force Awakens', 'The Last Jedi', 'The Rise of Skywalker' ]; $goodMovies = [0, 0, 0, 1, 1, 1, 1, 0, 0]; foreach (Single::compress($movies, $goodMovies) as $goodMovie) { print($goodMovie); } // 'A New Hope', 'Empire Strikes Back', 'Return of the Jedi', 'The Force Awakens'
Compress Associative
通过过滤掉未选择的键来压缩可迭代对象。
Single::compressAssociative(string $data, array $selectorKeys)
- 仅支持标准 PHP 数组/迭代器键(字符串,整数)。
use IterTools\Single; $starWarsEpisodes = [ 'I' => 'The Phantom Menace', 'II' => 'Attack of the Clones', 'III' => 'Revenge of the Sith', 'IV' => 'A New Hope', 'V' => 'The Empire Strikes Back', 'VI' => 'Return of the Jedi', 'VII' => 'The Force Awakens', 'VIII' => 'The Last Jedi', 'IX' => 'The Rise of Skywalker', ]; $originalTrilogyNumbers = ['IV', 'V', 'VI']; foreach (Single::compressAssociative($starWarsEpisodes, $originalTrilogyNumbers) as $episode => $title) { print("$episode: $title" . \PHP_EOL); } // IV: A New Hope // V: The Empire Strikes Back // VI: Return of the Jedi
Drop While
在谓词函数为 true 时从可迭代对象中删除元素。
一旦谓词函数返回 false,则返回所有剩余元素。
Single::dropWhile(iterable $data, callable $predicate)
use IterTools\Single; $scores = [50, 60, 70, 85, 65, 90]; $predicate = fn ($x) => $x < 70; foreach (Single::dropWhile($scores, $predicate) as $score) { print($score); } // 70, 85, 65, 90
过滤器
从可迭代对象中筛选元素,仅返回谓词函数为真的元素。
Single::filter(可迭代对象 $data, 谓词 $predicate)
use IterTools\Single; $starWarsEpisodes = [1, 2, 3, 4, 5, 6, 7, 8, 9]; $goodMoviePredicate = fn ($episode) => $episode > 3 && $episode < 8; foreach (Single::filter($starWarsEpisodes, $goodMoviePredicate) as $goodMovie) { print($goodMovie); } // 4, 5, 6, 7
筛选 True
从可迭代对象中筛选元素,仅返回真值元素。
Single::filterTrue(可迭代对象 $data)
use IterTools\Single; $reportCardGrades = [100, 0, 95, 85, 0, 94, 0]; foreach (Single::filterTrue($reportCardGrades) as $goodGrade) { print($goodGrade); } // 100, 95, 85, 94
筛选 False
从可迭代对象中筛选元素,仅返回谓词函数为假的元素。
如果没有提供谓词,则使用数据的布尔值。
Single::filterFalse(可迭代对象 $data, 谓词 $predicate)
use IterTools\Single; $alerts = [0, 1, 1, 0, 1, 0, 0, 1, 1]; foreach (Single::filterFalse($alerts) as $noAlert) { print($noAlert); } // 0, 0, 0, 0
筛选键
从可迭代对象中筛选元素,仅返回键的谓词函数为真的元素。
Single::filterKeys(可迭代对象 $data, 谓词 $predicate)
use IterTools\Single; $olympics = [ 2000 => 'Sydney', 2002 => 'Salt Lake City', 2004 => 'Athens', 2006 => 'Turin', 2008 => 'Beijing', 2010 => 'Vancouver', 2012 => 'London', 2014 => 'Sochi', 2016 => 'Rio de Janeiro', 2018 => 'Pyeongchang', 2020 => 'Tokyo', 2022 => 'Beijing', ]; $summerFilter = fn ($year) => $year % 4 === 0; foreach (Single::filterKeys($olympics, $summerFilter) as $year => $hostCity) { print("$year: $hostCity" . \PHP_EOL); } // 2000: Sydney // 2004: Athens // 2008: Beijing // 2012: London // 2016: Rio de Janeiro // 2020: Tokyo
扁平映射
仅对可迭代对象的元素映射一个函数,然后展开结果。
Single::flatMap(可迭代对象 $data, 映射器 $mapper)
use IterTools\Single; $data = [1, 2, 3, 4, 5]; $mapper = fn ($item) => [$item, -$item]; foreach (Single::flatMap($data, $mapper) as $number) { print($number . ' '); } // 1 -1 2 -2 3 -3 4 -4 5 -5
展开
展开多维可迭代对象。
Single::flatten(可迭代对象 $data, int $dimensions = 1)
use IterTools\Single; $multidimensional = [1, [2, 3], [4, 5]]; $flattened = []; foreach (Single::flatten($multidimensional) as $number) { $flattened[] = $number; } // [1, 2, 3, 4, 5]
按组
按公共数据元素分组数据。
Single::groupBy(可迭代对象 $data, 谓词 $groupKeyFunction, 谓词 $itemKeyFunction = null)
- $groupKeyFunction 决定了分组元素的关键字。
- 可选的 $itemKeyFunction 允许在每组成员中自定义索引。
use IterTools\Single; $cartoonCharacters = [ ['Garfield', 'cat'], ['Tom', 'cat'], ['Felix', 'cat'], ['Heathcliff', 'cat'], ['Snoopy', 'dog'], ['Scooby-Doo', 'dog'], ['Odie', 'dog'], ['Donald', 'duck'], ['Daffy', 'duck'], ]; $charactersGroupedByAnimal = []; foreach (Single::groupBy($cartoonCharacters, fn ($x) => $x[1]) as $animal => $characters) { $charactersGroupedByAnimal[$animal] = $characters; } /* 'cat' => [ ['Garfield', 'cat'], ['Tom', 'cat'], ['Felix', 'cat'], ['Heathcliff', 'cat'], ], 'dog' => [ ['Snoopy', 'dog'], ['Scooby-Doo', 'dog'], ['Odie', 'dog'], ], 'duck' => [ ['Donald', 'duck'], ['Daffy', 'duck'], */
限制
迭代到限制。
如果达到限制,则停止迭代,即使还有更多数据可用。
Single::limit(可迭代对象 $data, int $limit)
use IterTools\Single; $matrixMovies = ['The Matrix', 'The Matrix Reloaded', 'The Matrix Revolutions', 'The Matrix Resurrections']; $limit = 1; foreach (Single::limit($matrixMovies, $limit) as $goodMovie) { print($goodMovie); } // 'The Matrix' (and nothing else)
映射
将函数映射到每个元素。
Single::map(可迭代对象 $data, 函数 $function)
use IterTools\Single; $grades = [100, 99, 95, 98, 100]; $strictParentsOpinion = fn ($g) => $g === 100 ? 'A' : 'F'; foreach (Single::map($grades, $strictParentsOpinion) as $actualGrade) { print($actualGrade); } // A, F, F, F, A
成对
返回连续重叠的对。
如果给定的集合包含少于2个元素,则返回空生成器。
Single::pairwise(可迭代对象 $data)
use IterTools\Single; $friends = ['Ross', 'Rachel', 'Chandler', 'Monica', 'Joey', 'Phoebe']; foreach (Single::pairwise($friends) as [$leftFriend, $rightFriend]) { print("{$leftFriend} and {$rightFriend}"); } // Ross and Rachel, Rachel and Chandler, Chandler and Monica, ...
重复
重复一个项目。
Single::repeat(混合 $item, int $repetitions)
use IterTools\Single; $data = 'Beetlejuice'; $repetitions = 3; foreach (Single::repeat($data, $repetitions) as $repeated) { print($repeated); } // 'Beetlejuice', 'Beetlejuice', 'Beetlejuice'
重索引
使用索引器函数重索引键值可迭代对象的键。
Single::reindex(string $data, 函数 $indexer)
use IterTools\Single; $data = [ [ 'title' => 'Star Wars: Episode IV – A New Hope', 'episode' => 'IV', 'year' => 1977, ], [ 'title' => 'Star Wars: Episode V – The Empire Strikes Back', 'episode' => 'V', 'year' => 1980, ], [ 'title' => 'Star Wars: Episode VI – Return of the Jedi', 'episode' => 'VI', 'year' => 1983, ], ]; $reindexFunc = fn (array $swFilm) => $swFilm['episode']; $reindexedData = []; foreach (Single::reindex($data, $reindexFunc) as $key => $filmData) { $reindexedData[$key] = $filmData; } // [ // 'IV' => [ // 'title' => 'Star Wars: Episode IV – A New Hope', // 'episode' => 'IV', // 'year' => 1977, // ], // 'V' => [ // 'title' => 'Star Wars: Episode V – The Empire Strikes Back', // 'episode' => 'V', // 'year' => 1980, // ], // 'VI' => [ // 'title' => 'Star Wars: Episode VI – Return of the Jedi', // 'episode' => 'VI', // 'year' => 1983, // ], // ]
反转
反转可迭代对象的元素。
Single::reverse(可迭代对象 $data)
use IterTools\Single; $words = ['Alice', 'answers', 'your', 'questions', 'Bob']; foreach (Single::reverse($words) as $word) { print($word . ' '); } // Bob questions your answers Alice
跳过
在可选偏移量 offset 后跳过可迭代对象中的 n 个元素。
Single::skip(可迭代对象 $data, int $count, int $offset = 0)
use IterTools\Single; $movies = [ 'The Phantom Menace', 'Attack of the Clones', 'Revenge of the Sith', 'A New Hope', 'The Empire Strikes Back', 'Return of the Jedi', 'The Force Awakens', 'The Last Jedi', 'The Rise of Skywalker' ]; $prequelsRemoved = []; foreach (Single::skip($movies, 3) as $nonPrequel) { $prequelsRemoved[] = $nonPrequel; } // Episodes IV - IX $onlyTheBest = []; foreach (Single::skip($prequelsRemoved, 3, 3) as $nonSequel) { $onlyTheBest[] = $nonSequel; } // 'A New Hope', 'The Empire Strikes Back', 'Return of the Jedi'
切片
提取可迭代对象的一部分。
Single::slice(可迭代对象 $data, int $start = 0, int $count = null, int $step = 1)
use IterTools\Single; $olympics = [1992, 1994, 1996, 1998, 2000, 2002, 2004, 2006, 2008, 2010, 2012, 2014, 2016, 2018, 2020, 2022]; $winterOlympics = []; foreach (Single::slice($olympics, 1, 8, 2) as $winterYear) { $winterOlympics[] = $winterYear; } // [1994, 1998, 2002, 2006, 2010, 2014, 2018, 2022]
字符串
迭代字符串的各个字符。
Single::string(string $string)
use IterTools\Single; $string = 'MickeyMouse'; $listOfCharacters = []; foreach (Single::string($string) as $character) { $listOfCharacters[] = $character; } // ['M', 'i', 'c', 'k', 'e', 'y', 'M', 'o', 'u', 's', 'e']
Take While
只要谓词为真,就返回可迭代对象的元素。
停止迭代,即使后面的元素最终会返回真(与 filterTrue 不同)。
Single::takeWhile(可迭代对象 $data, 谓词 $predicate)
use IterTools\Single; $prices = [0, 0, 5, 10, 0, 0, 9]; $isFree = fn ($price) => $price == 0; foreach (Single::takeWhile($prices, $isFree) as $freePrice) { print($freePrice); } // 0, 0
无限迭代
计数
永远按顺序计数。
Infinite::count(int $start = 1, int $step = 1)
use IterTools\Infinite; $start = 1; $step = 1; foreach (Infinite::count($start, $step) as $i) { print($i); } // 1, 2, 3, 4, 5 ...
循环
无限期地按顺序遍历集合的元素。
Infinite::cycle(可迭代对象 $iterable)
use IterTools\Infinite; $hands = ['rock', 'paper', 'scissors']; foreach (Infinite::cycle($hands) as $hand) { RockPaperScissors::playHand($hand); } // rock, paper, scissors, rock, paper, scissors, ...
重复 (无限)
无限期地重复一个项目。
Infinite::repeat(混合 $item)
use IterTools\Infinite; $dialogue = 'Are we there yet?'; foreach (Infinite::repeat($dialogue) as $repeated) { print($repeated); } // 'Are we there yet?', 'Are we there yet?', 'Are we there yet?', ...
随机迭代
选择
从值数组中生成随机选择。
Random::choice(array $items, int $repetitions)
use IterTools\Random; $cards = ['Ace', 'King', 'Queen', 'Jack', 'Joker']; $repetitions = 10; foreach (Random::choice($cards, $repetitions) as $card) { print($card); } // 'King', 'Jack', 'King', 'Ace', ... [random]
抛硬币
生成随机抛硬币结果(0或1)。
Random::coinFlip(int $repetitions)
use IterTools\Random; $repetitions = 10; foreach (Random::coinFlip($repetitions) as $coinFlip) { print($coinFlip); } // 1, 0, 1, 1, 0, ... [random]
数字
生成随机数字(整数)。
Random::number(int $min, int $max, int $repetitions)
use IterTools\Random; $min = 1; $max = 4; $repetitions = 10; foreach (Random::number($min, $max, $repetitions) as $number) { print($number); } // 3, 2, 5, 5, 1, 2, ... [random]
百分比
生成介于0和1之间的随机百分比。
Random::percentage(int $repetitions)
use IterTools\Random; $repetitions = 10; foreach (Random::percentage($repetitions) as $percentage) { print($percentage); } // 0.30205562629132, 0.59648594775233, ... [random]
剪刀石头布
生成随机的剪刀石头布手势。
Random::rockPaperScissors(int $repetitions)
use IterTools\Random; $repetitions = 10; foreach (Random::rockPaperScissors($repetitions) as $rpsHand) { print($rpsHand); } // 'paper', 'rock', 'rock', 'scissors', ... [random]
数学迭代
频率
返回数据的频率分布。
Math::frequencies(可迭代对象 $data, bool $strict = true): \Generator
默认为严格类型比较。将严格设置为 false 以进行类型强制比较。
use IterTools\Math; $grades = ['A', 'A', 'B', 'B', 'B', 'C']; foreach (Math::frequencies($grades) as $grade => $frequency) { print("$grade: $frequency" . \PHP_EOL); } // A: 2, B: 3, C: 1
相对频率
返回数据的相对频率分布。
Math::relativeFrequencies(可迭代对象 $data, bool $strict = true): \Generator
默认为严格类型比较。将严格设置为 false 以进行类型强制比较。
use IterTools\Math; $grades = ['A', 'A', 'B', 'B', 'B', 'C']; foreach (Math::relativeFrequencies($grades) as $grade => $frequency) { print("$grade: $frequency" . \PHP_EOL); } // A: 0.33, B: 0.5, C: 0.166
移动平均
计算数字列表上的移动平均。
Math::runningAverage(数字 $numbers, int|float $initialValue = null)
use IterTools\Math; $grades = [100, 80, 80, 90, 85]; foreach (Math::runningAverage($grades) as $runningAverage) { print($runningAverage); } // 100, 90, 86.667, 87.5, 87
运行差分
对一列数字的运行差分进行累积。
Math::runningDifference(iterable $numbers, int|float $initialValue = null)
use IterTools\Math; $credits = [1, 2, 3, 4, 5]; foreach (Math::runningDifference($credits) as $runningDifference) { print($runningDifference); } // -1, -3, -6, -10, -15
提供一个可选的初始值以引导运行差分。
use IterTools\Math; $dartsScores = [50, 50, 25, 50]; $startingScore = 501; foreach (Math::runningDifference($dartsScores, $startingScore) as $runningScore) { print($runningScore); } // 501, 451, 401, 376, 326
运行最大值
对一列数字的运行最大值进行累积。
Math::runningMax(iterable $numbers, int|float $initialValue = null)
use IterTools\Math; $numbers = [1, 2, 1, 3, 5]; foreach (Math::runningMax($numbers) as $runningMax) { print($runningMax); } // 1, 2, 2, 3, 5
运行最小值
对一列数字的运行最小值进行累积。
Math::runningMin(iterable $numbers, int|float $initialValue = null)
use IterTools\Math; $numbers = [3, 4, 2, 5, 1]; foreach (Math::runningMin($numbers) as $runningMin) { print($runningMin); } // 3, 3, 2, 2, 1
运行乘积
对一列数字的运行乘积进行累积。
Math::runningProduct(iterable $numbers, int|float $initialValue = null)
use IterTools\Math; $numbers = [1, 2, 3, 4, 5]; foreach (Math::runningProduct($numbers) as $runningProduct) { print($runningProduct); } // 1, 2, 6, 24, 120
提供一个可选的初始值以引导运行乘积。
use IterTools\Math; $numbers = [1, 2, 3, 4, 5]; $initialValue = 5; foreach (Math::runningProduct($numbers, $initialValue) as $runningProduct) { print($runningProduct); } // 5, 5, 10, 30, 120, 600
运行总计
对一列数字的运行总计进行累积。
Math::runningTotal(iterable $numbers, int|float $initialValue = null)
use IterTools\Math; $prices = [1, 2, 3, 4, 5]; foreach (Math::runningTotal($prices) as $runningTotal) { print($runningTotal); } // 1, 3, 6, 10, 15
提供一个可选的初始值以引导运行总计。
use IterTools\Math; $prices = [1, 2, 3, 4, 5]; $initialValue = 5; foreach (Math::runningTotal($prices, $initialValue) as $runningTotal) { print($runningTotal); } // 5, 6, 8, 11, 15, 20
集合和多集
区分
从可迭代对象中过滤出元素,仅返回不同的元素。
Set::distinct(iterable $data, bool $strict = true)
默认为严格类型比较。将严格设置为 false 以进行类型强制比较。
use IterTools\Set; $chessSet = ['rook', 'rook', 'knight', 'knight', 'bishop', 'bishop', 'king', 'queen', 'pawn', 'pawn', ... ]; foreach (Set::distinct($chessSet) as $chessPiece) { print($chessPiece); } // rook, knight, bishop, king, queen, pawn $mixedTypes = [1, '1', 2, '2', 3]; foreach (Set::distinct($mixedTypes, false) as $datum) { print($datum); } // 1, 2, 3
根据函数区分
从可迭代对象中过滤出元素,仅返回根据自定义比较函数不同的元素。
Set::distinctBy(iterable $data, callable $compareBy)
use IterTools\Set; $streetFighterConsoleReleases = [ ['id' => '112233', 'name' => 'Street Fighter 3 3rd Strike', 'console' => 'Dreamcast'], ['id' => '223344', 'name' => 'Street Fighter 3 3rd Strike', 'console' => 'PS4'], ['id' => '334455', 'name' => 'Street Fighter 3 3rd Strike', 'console' => 'PS5'], ['id' => '445566', 'name' => 'Street Fighter VI', 'console' => 'PS4'], ['id' => '556677', 'name' => 'Street Fighter VI', 'console' => 'PS5'], ['id' => '667788', 'name' => 'Street Fighter VI', 'console' => 'PC'], ]; $compareBy = fn ($sfTitle) => $sfTitle['name']; $uniqueTitles = []; foreach (Set::distinctBy($streetFighterConsoleReleases, $compareBy) as $sfTitle) { $uniqueTitles[] = $sfTitle; } // Contains one SF3 3rd Strike entry and one SFVI entry.
交集
迭代可迭代对象的交集。
Set::intersection(iterable ...$iterables)
如果输入的可迭代对象产生重复项,则应用多重集交集规则。
use IterTools\Set; $chessPieces = ['rook', 'knight', 'bishop', 'queen', 'king', 'pawn']; $shogiPieces = ['rook', 'knight', 'bishop' 'king', 'pawn', 'lance', 'gold general', 'silver general']; foreach (Set::intersection($chessPieces, $shogiPieces) as $commonPiece) { print($commonPiece); } // rook, knight, bishop, king, pawn
强制交集
使用类型强制迭代可迭代对象的交集。
Set::intersectionCoercive(iterable ...$iterables)
如果输入的可迭代对象产生重复项,则应用多重集交集规则。
use IterTools\Set; $numbers = [1, 2, 3, 4, 5]; $numerics = ['1', '2', 3]; foreach (Set::intersectionCoercive($numbers, $numerics) as $commonNumber) { print($commonNumber); } // 1, 2, 3
部分交集
迭代可迭代对象的M-部分交集。
Set::partialIntersection(int $minIntersectionCount, iterable ...$iterables)
- 如果输入的可迭代对象产生重复项,则应用多重集交集规则。
use IterTools\Set; $staticallyTyped = ['c++', 'java', 'c#', 'go', 'haskell']; $dynamicallyTyped = ['php', 'python', 'javascript', 'typescript']; $supportsInterfaces = ['php', 'java', 'c#', 'typescript']; foreach (Set::partialIntersection(2, $staticallyTyped, $dynamicallyTyped, $supportsInterfaces) as $language) { print($language); } // c++, java, c#, go, php
部分强制交集
Set::partialIntersectionCoercive(int $minIntersectionCount, iterable ...$iterables)
- 如果输入的可迭代对象产生重复项,则应用多重集交集规则。
use IterTools\Set; $set1 = [1, 2, 3], $set2 = ['2', '3', 4, 5], $set3 = [1, '2'], foreach (Set::partialIntersectionCoercive(2, $set1, $set2, $set3) as $partiallyCommonNumber) { print($partiallyCommonNumber); } // 1, 2, 3
对称差分
迭代可迭代对象的对称差分。
Set::symmetricDifference(iterable ...$iterables)
如果输入的可迭代对象产生重复项,则应用多重集差分规则。
use IterTools\Set; $a = [1, 2, 3, 4, 7]; $b = ['1', 2, 3, 5, 8]; $c = [1, 2, 3, 6, 9]; foreach (Set::symmetricDifference($a, $b, $c) as $item) { print($item); } // 1, 4, 5, 6, 7, 8, 9
对称差分强制
使用类型强制迭代可迭代对象的对称差分。
Set::symmetricDifferenceCoercive(iterable ...$iterables)
如果输入的可迭代对象产生重复项,则应用多重集差分规则。
use IterTools\Set; $a = [1, 2, 3, 4, 7]; $b = ['1', 2, 3, 5, 8]; $c = [1, 2, 3, 6, 9]; foreach (Set::symmetricDifferenceCoercive($a, $b, $c) as $item) { print($item); } // 4, 5, 6, 7, 8, 9
并集
迭代可迭代对象的并集。
Set::union(iterable ...$iterables)
如果输入的可迭代对象产生重复项,则应用多重集并集规则。
use IterTools\Set; $a = [1, 2, 3]; $b = [3, 4]; $c = [1, 2, 3, 6, 7]; foreach (Set::union($a, $b, $c) as $item) { print($item); } //1, 2, 3, 4, 6, 7
并集强制
使用类型强制迭代可迭代对象的并集。
Set::unionCoercive(iterable ...$iterables)
如果输入的可迭代对象产生重复项,则应用多重集并集规则。
use IterTools\Set; $a = ['1', 2, 3]; $b = [3, 4]; $c = [1, 2, 3, 6, 7]; foreach (Set::unionCoercive($a, $b, $c) as $item) { print($item); } //1, 2, 3, 4, 6, 7
排序迭代
ASort
迭代排序的集合,同时保持关联键索引关系。
Sort::sort(iterable $data, callable $comparator = null)
如果没有提供可选的比较函数,则使用默认排序。
use IterTools\Single; $worldPopulations = [ 'China' => 1_439_323_776, 'India' => 1_380_004_385, 'Indonesia' => 273_523_615, 'Pakistan' => 220_892_340, 'USA' => 331_002_651, ]; foreach (Sort::sort($worldPopulations) as $country => $population) { print("$country: $population" . \PHP_EOL); } // Pakistan: 220,892,340 // Indonesia: 273,523,615 // USA: 331,002,651 // India: 1,380,004,385 // China: 1,439,323,776
Sort
迭代排序的集合。
Sort::sort(iterable $data, callable $comparator = null)
如果没有提供可选的比较函数,则使用默认排序。
use IterTools\Single; $data = [3, 4, 5, 9, 8, 7, 1, 6, 2]; foreach (Sort::sort($data) as $datum) { print($datum); } // 1, 2, 3, 4, 5, 6, 7, 8, 9
文件
读取CSV
迭代CSV文件的行。
File::readCsv(resource $fileHandle, string $separator = ',', string $enclosure = '"', string $escape = '\\')
use IterTools\File; $fileHandle = \fopen('path/to/file.csv', 'r'); foreach (File::readCsv($fileHandle) as $row) { print_r($row); } // Each column field is an element of the array
读取行
迭代文件的行。
File::readLines(resource $fileHandle)
use IterTools\File; $fileHandle = \fopen('path/to/file.txt', 'r'); foreach (File::readLines($fileHandle) as $line) { print($line); }
转换
分叉
从单个可迭代对象返回几个独立(重复)的迭代器。
Transform::tee(iterable $data, int $count): array
use IterTools\Transform; $daysOfWeek = ['Mon', 'Tues', 'Wed', 'Thurs', 'Fri', 'Sat', 'Sun']; $count = 3; [$week1, $week2, $week3] = Transform::tee($data, $count); // Each $week contains iterator containing ['Mon', 'Tues', 'Wed', 'Thurs', 'Fri', 'Sat', 'Sun']
转为数组
将任何可迭代对象转换为数组。
Transform::toArray(iterable $data): array
use IterTools\Transform; $iterator = new \ArrayIterator([1, 2, 3, 4, 5]); $array = Transform::toArray($iterator);
转为关联数组
将任何可迭代对象转换为关联数组。
Transform::toAssociativeArray(iterable $data, callable $keyFunc = null, callable $valueFunc = null): array
use IterTools\Transform; $messages = ['message 1', 'message 2', 'message 3']; $keyFunc = fn ($msg) => \md5($msg); $valueFunc = fn ($msg) => strtoupper($msg); $associativeArray = Transform::toAssociativeArray($messages, $keyFunc, $valueFunc); // [ // '1db65a6a0a818fd39655b95e33ada11d' => 'MESSAGE 1', // '83b2330607fe8f817ce6d24249dea373' => 'MESSAGE 2', // '037805d3ad7b10c5b8425427b516b5ce' => 'MESSAGE 3', // ]
转换为迭代器
将任何可迭代对象转换为迭代器。
Transform::toArray(iterable $data): array
use IterTools\Transform; $array = [1, 2, 3, 4, 5]; $iterator = Transform::toIterator($array);
总结
全部匹配
如果所有元素都匹配谓词函数,则返回 true。
Summary::allMatch(iterable $data, callable $predicate): bool
use IterTools\Summary; $finalFantasyNumbers = [4, 5, 6]; $isOnSuperNintendo = fn ($ff) => $ff >= 4 && $ff <= 6; $boolean = Summary::allMatch($finalFantasyNumbers, $isOnSuperNintendo); // true $isOnPlaystation = fn ($ff) => $ff >= 7 && $ff <= 9; $boolean = Summary::allMatch($finalFantasyNumbers, $isOnPlaystation); // false
全部唯一
如果所有元素都是唯一的,则返回 true。
Summary::allUnique(iterable $data, bool $strict = true): bool
默认为严格类型比较。将严格设置为 false 以进行类型强制比较。
use IterTools\Summary; $items = ['fingerprints', 'snowflakes', 'eyes', 'DNA'] $boolean = Summary::allUnique($items); // true
任意匹配
如果任何元素匹配谓词函数,则返回 true。
Summary::anyMatch(iterable $data, callable $predicate): bool
use IterTools\Summary; $answers = ['fish', 'towel', 42, "don't panic"]; $isUltimateAnswer = fn ($a) => a == 42; $boolean = Summary::anyMatch($answers, $isUltimateAnswer); // true
是否是排列
如果所有可迭代对象都是彼此的排列,则返回 true。
Summary::arePermutations(iterable ...$iterables): bool
use IterTools\Summary; $iter = ['i', 't', 'e', 'r']; $rite = ['r', 'i', 't', 'e']; $reit = ['r', 'e', 'i', 't']; $tier = ['t', 'i', 'e', 'r']; $tire = ['t', 'i', 'r', 'e']; $trie = ['t', 'r', 'i', 'e']; $boolean = Summary::arePermutations($iter, $rite, $reit, $tier, $tire, $trie); // true
是否是强排列
如果所有可迭代对象都是彼此的排列,并且进行了类型转换,则返回 true。
Summary::arePermutationsCoercive(iterable ...$iterables): bool
use IterTools\Summary; $set1 = [1, 2.0, '3']; $set2 = [2.0, '1', 3]; $set3 = [3, 2, 1]; $boolean = Summary::arePermutationsCoercive($set1, $set2, $set3); // true
正好 N 个
如果根据谓词函数正好有 n 个元素为 true,则返回 true。
- 谓词是可选的。
- 默认谓词是每个项的布尔值。
Summary::exactlyN(iterable $data, int $n, callable $predicate): bool
use IterTools\Summary; $twoTruthsAndALie = [true, true, false]; $n = 2; $boolean = Summary::exactlyN($twoTruthsAndALie, $n); // true $ages = [18, 21, 24, 54]; $n = 4; $predicate = fn ($age) => $age >= 21; $boolean = Summary::exactlyN($ages, $n, $predicate); // false
是否为空
如果可迭代对象为空且没有项目,则返回 true。
Summary::isEmpty(iterable $data): bool
use IterTools\Summary; $data = [] $boolean = Summary::isEmpty($data); // true
是否已分割
如果给定集合中满足谓词的所有元素都出现在不满足谓词的所有元素之前,则返回 true。
- 对于空集合或单个项目的集合,返回 true。
- 如果没有提供,默认谓词是每个数据项的布尔值。
Summary::isPartitioned(iterable $data, callable $predicate = null): bool
use IterTools\Summary; $numbers = [0, 2, 4, 1, 3, 5]; $evensBeforeOdds = fn ($item) => $item % 2 === 0; $boolean = Summary::isPartitioned($numbers, $evensBeforeOdds);
是否已排序
如果元素已排序,则返回 true,否则返回 false。
- 元素必须是可比较的。
- 如果为空或只有一个元素,则返回 true。
Summary::isSorted(iterable $data): bool
use IterTools\Summary; $numbers = [1, 2, 3, 4, 5]; $boolean = Summary::isSorted($numbers); // true $numbers = [3, 2, 3, 4, 5]; $boolean = Summary::isSorted($numbers); // false
是否已反转
如果元素是逆序排序的,则返回 true,否则返回 false。
- 元素必须是可比较的。
- 如果为空或只有一个元素,则返回 true。
Summary::isReversed(iterable $data): bool
use IterTools\Summary; $numbers = [5, 4, 3, 2, 1]; $boolean = Summary::isReversed($numbers); // true $numbers = [1, 4, 3, 2, 1]; $boolean = Summary::isReversed($numbers); // false
没有匹配
如果没有元素匹配谓词函数,则返回 true。
Summary::noneMatch(iterable $data, callable $predicate): bool
use IterTools\Summary; $grades = [45, 50, 61, 0]; $isPassingGrade = fn ($grade) => $grade >= 70; $boolean = Summary::noneMatch($grades, $isPassingGrade); // true
相同
如果所有给定的集合都相同,则返回 true。
对于单个可迭代对象或空可迭代对象列表,返回 true。
Summary::same(iterable ...$iterables): bool
use IterTools\Summary; $cocaColaIngredients = ['carbonated water', 'sugar', 'caramel color', 'phosphoric acid']; $pepsiIngredients = ['carbonated water', 'sugar', 'caramel color', 'phosphoric acid']; $boolean = Summary::same($cocaColaIngredients, $pepsiIngredients); // true $cocaColaIngredients = ['carbonated water', 'sugar', 'caramel color', 'phosphoric acid']; $spriteIngredients = ['carbonated water', 'sugar', 'citric acid', 'lemon lime flavorings']; $boolean = Summary::same($cocaColaIngredients, $spriteIngredients); // false
相同计数
如果所有给定的集合具有相同的长度,则返回 true。
对于单个可迭代对象或空可迭代对象列表,返回 true。
Summary::sameCount(iterable ...$iterables): bool
use IterTools\Summary; $prequels = ['Phantom Menace', 'Attack of the Clones', 'Revenge of the Sith']; $originals = ['A New Hope', 'Empire Strikes Back', 'Return of the Jedi']; $sequels = ['The Force Awakens', 'The Last Jedi', 'The Rise of Skywalker']; $boolean = Summary::sameCount($prequels, $originals, $sequels); // true $batmanMovies = ['Batman Begins', 'The Dark Knight', 'The Dark Knight Rises']; $matrixMovies = ['The Matrix', 'The Matrix Reloaded', 'The Matrix Revolutions', 'The Matrix Resurrections']; $result = Summary::sameCount($batmanMovies, $matrixMovies); // false
减少
转换为平均值
转换为平均值。
如果集合为空,则返回 null。
Reduce::toAverage(iterable $data): float
use IterTools\Reduce; $grades = [100, 90, 95, 85, 94]; $finalGrade = Reduce::toAverage($numbers); // 92.8
转换为计数
将可迭代对象转换为它的长度。
Reduce::toCount(iterable $data): int
use IterTools\Reduce; $someIterable = ImportantThing::getCollectionAsIterable(); $length = Reduce::toCount($someIterable); // 3
转换为第一个
将可迭代对象转换为它的第一个元素。
Reduce::toFirst(iterable $data): mixed
如果集合为空,则抛出 \LengthException
。
use IterTools\Reduce; $medals = ['gold', 'silver', 'bronze']; $first = Reduce::toFirst($medals); // gold
转换为第一个和最后一个
将可迭代对象转换为它的第一个和最后一个元素。
Reduce::toFirstAndLast(iterable $data): array{mixed, mixed}
如果集合为空,则抛出 \LengthException
。
use IterTools\Reduce; $weekdays = ['Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday']; $firstAndLast = Reduce::toFirstAndLast($weekdays); // [Monday, Friday]
转换为最后一个
将可迭代对象转换为它的最后一个元素。
Reduce::toLast(iterable $data): mixed
如果集合为空,则抛出 \LengthException
。
use IterTools\Reduce; $gnomesThreePhasePlan = ['Collect underpants', '?', 'Profit']; $lastPhase = Reduce::toLast($gnomesThreePhasePlan); // Profit
转换为最大值
转换为最大值。
Reduce::toMax(iterable $data, callable $compareBy = null): mixed|null
- 可选的可调用参数
$compareBy
必须返回可比较的值。 - 如果没有提供
$compareBy
,则给定集合的项必须是可比较的。 - 如果集合为空,则返回 null。
use IterTools\Reduce; $numbers = [5, 3, 1, 2, 4]; $result = Reduce::toMax($numbers); // 5 $movieRatings = [ [ 'title' => 'Star Wars: Episode IV - A New Hope', 'rating' => 4.6 ], [ 'title' => 'Star Wars: Episode V - The Empire Strikes Back', 'rating' => 4.8 ], [ 'title' => 'Star Wars: Episode VI - Return of the Jedi', 'rating' => 4.6 ], ]; $compareBy = fn ($movie) => $movie['rating']; $highestRatedMovie = Reduce::toMax($movieRatings, $compareBy); // [ // 'title' => 'Star Wars: Episode V - The Empire Strikes Back', // 'rating' => 4.8 // ];
转换为最小值
转换为最小值。
Reduce::toMin(iterable $data, callable $compareBy = null): mixed|null
- 可选的可调用参数
$compareBy
必须返回可比较的值。 - 如果没有提供
$compareBy
,则给定集合的项必须是可比较的。 - 如果集合为空,则返回 null。
use IterTools\Reduce; $numbers = [5, 3, 1, 2, 4]; $result = Reduce::toMin($numbers); // 1 $movieRatings = [ [ 'title' => 'The Matrix', 'rating' => 4.7 ], [ 'title' => 'The Matrix Reloaded', 'rating' => 4.3 ], [ 'title' => 'The Matrix Revolutions', 'rating' => 3.9 ], [ 'title' => 'The Matrix Resurrections', 'rating' => 2.5 ], ]; $compareBy = fn ($movie) => $movie['rating']; $lowestRatedMovie = Reduce::toMin($movieRatings, $compareBy); // [ // 'title' => 'The Matrix Resurrections', // 'rating' => 2.5 // ]
转换为最大最小值
转换为包含其上界和下界(最大值和最小值)的数组。
Reduce::toMinMax(iterable $numbers, callable $compareBy = null): array
- 可选的可调用参数
$compareBy
必须返回可比较的值。 - 如果没有提供
$compareBy
,则给定集合的项必须是可比较的。 - 如果给定的集合为空,则返回
[null, null]
。
use IterTools\Reduce; $numbers = [1, 2, 7, -1, -2, -3]; [$min, $max] = Reduce::toMinMax($numbers); // [-3, 7] $reportCard = [ [ 'subject' => 'history', 'grade' => 90 ], [ 'subject' => 'math', 'grade' => 98 ], [ 'subject' => 'science', 'grade' => 92 ], [ 'subject' => 'english', 'grade' => 85 ], [ 'subject' => 'programming', 'grade' => 100 ], ]; $compareBy = fn ($class) => $class['grade']; $bestAndWorstSubject = Reduce::toMinMax($reportCard, $compareBy); // [ // [ // 'subject' => 'english', // 'grade' => 85 // ], // [ // 'subject' => 'programming', // 'grade' => 100 // ], // ]
转换为第 N 个
转换为第 n 个位置上的值。
Reduce::toNth(iterable $data, int $position): mixed
use IterTools\Reduce; $lotrMovies = ['The Fellowship of the Ring', 'The Two Towers', 'The Return of the King']; $rotk = Reduce::toNth($lotrMovies, 2); // 20
转换为乘积
转换为元素的乘积。
如果集合为空,则返回 null。
Reduce::toProduct(iterable $data): number|null
use IterTools\Reduce; $primeFactors = [5, 2, 2]; $number = Reduce::toProduct($primeFactors); // 20
到随机值
将给定集合缩减为其中的一个随机值。
Reduce::toRandomValue(iterable $data): mixed
use IterTools\Reduce; $sfWakeupOptions = ['mid', 'low', 'overhead', 'throw', 'meaty']; $wakeupOption = Reduce::toRandomValue($sfWakeupOptions); // e.g., throw
到范围
将给定集合缩减为其范围(最大值和最小值之间的差)。
Reduce::toRange(iterable $numbers): int|float
如果可迭代表达式为空,则返回 0
。
use IterTools\Reduce; $grades = [100, 90, 80, 85, 95]; $range = Reduce::toRange($numbers); // 20
到字符串
将所有元素缩减为一个字符串连接。
- 在项目之间插入的可选分隔符。
- 字符串前可选的前缀。
- 字符串后可选的后缀。
Reduce::toString(iterable $data, string $separator = '', string $prefix = '', string $suffix = ''): string
use IterTools\Reduce; $words = ['IterTools', 'PHP', 'v1.0']; $string = Reduce::toString($words); // IterToolsPHPv1.0 $string = Reduce::toString($words, '-'); // IterTools-PHP-v1.0 $string = Reduce::toString($words, '-', 'Library: '); // Library: IterTools-PHP-v1.0 $string = Reduce::toString($words, '-', 'Library: ', '!'); // Library: IterTools-PHP-v1.0!
到总和
缩减为其元素的求和。
Reduce::toSum(iterable $data): number
use IterTools\Reduce; $parts = [10, 20, 30]; $sum = Reduce::toSum($parts); // 60
到值
使用缩减函数将元素缩减到单个值。
Reduce::toValue(iterable $data, callable $reducer, mixed $initialValue): mixed
use IterTools\Reduce; $input = [1, 2, 3, 4, 5]; $sum = fn ($carry, $item) => $carry + $item; $result = Reduce::toValue($input, $sum, 0); // 15
流
流提供了一个流畅的接口,通过一系列操作将数组和可迭代表达式转换为流。
流由以下组成
- 一个流源工厂方法来创建流。
- 零个或多个流操作符,将流转换为新的流。
- 终端操作之一
- 流的终端操作将流转换为值或数据结构。
$result = Stream::of([1, 1, 2, 2, 3, 4, 5]) ->distinct() // [1, 2, 3, 4, 5] ->map(fn ($x) => $x**2) // [1, 4, 9, 16, 25] ->filter(fn ($x) => $x < 10) // [1, 4, 9] ->toSum(); // 14
- 通过
foreach
循环迭代流。
$result = Stream::of([1, 1, 2, 2, 3, 4, 5]) ->distinct() // [1, 2, 3, 4, 5] ->map(fn ($x) => $x**2) // [1, 4, 9, 16, 25] ->filter(fn ($x) => $x < 10); // [1, 4, 9] foreach ($result as $item) { // 1, 4, 9 }
流源
的
从可迭代表达式中创建流。
Stream::of(iterable $iterable): Stream
use IterTools\Stream; $iterable = [1, 2, 3]; $result = Stream::of($iterable) ->chainWith([4, 5, 6], [7, 8, 9]) ->zipEqualWith([1, 2, 3, 4, 5, 6, 7, 8, 9]) ->toValue(fn ($carry, $item) => $carry + array_sum($item)); // 90
硬币翻转的
创建 n 次随机硬币翻转的流。
Stream::ofCoinFlips(int $repetitions): Stream
use IterTools\Stream; $result = Stream::ofCoinFlips(10) ->filterTrue() ->toCount(); // 5 (random)
CSV 文件
创建 CSV 文件的行流。
Stream::ofCsvFile(resource $fileHandle, string $separator = ',', string $enclosure = '"', string $escape = '\\'): Stream
use IterTools\Stream; $fileHandle = \fopen('path/to/file.csv', 'r'); $result = Stream::of($fileHandle) ->toArray();
空的
创建一个空流。
Stream::ofEmpty(): Stream
use IterTools\Stream; $result = Stream::ofEmpty() ->chainWith([1, 2, 3]) ->toArray(); // 1, 2, 3
文件行
创建文件行的流。
Stream::ofFileLines(resource $fileHandle): Stream
use IterTools\Stream; $fileHandle = \fopen('path/to/file.txt', 'r'); $result = Stream::of($fileHandle) ->map('strtoupper'); ->toArray();
随机选择
从值数组中创建随机选择的流。
Stream::ofRandomChoice(array $items, int $repetitions): Stream
use IterTools\Stream; $languages = ['PHP', 'Go', 'Python']; $languages = Stream::ofRandomChoice($languages, 5) ->toArray(); // 'Go', 'PHP', 'Python', 'PHP', 'PHP' (random)
随机数字
创建随机数字(整数)的流。
Stream::ofRandomNumbers(int $min, int $max, int $repetitions): Stream
use IterTools\Stream; $min = 1; $max = 3; $reps = 7; $result = Stream::ofRandomNumbers($min, $max, $reps) ->toArray(); // 1, 2, 2, 1, 3, 2, 1 (random)
随机百分比
创建介于 0 和 1 之间的随机百分比的流。
Stream::ofRandomPercentage(int $repetitions): Stream
use IterTools\Stream; $stream = Stream::ofRandomPercentage(3) ->toArray(); // 0.8012566976245, 0.81237281724151, 0.61676896329459 [random]
范围
创建数字范围的流。
Stream::ofRange(int|float $start, int|float $end, int|float $step = 1): Stream
use IterTools\Stream; $numbers = Stream::ofRange(0, 5) ->toArray(); // 0, 1, 2, 3, 4, 5
剪刀石头布
创建剪刀石头布手势的流。
Stream::ofRockPaperScissors(int $repetitions): Stream
use IterTools\Stream; $rps = Stream::ofRockPaperScissors(5) ->toArray(); // 'paper', 'rock', 'rock', 'scissors', 'paper' [random]
流操作
ASort
排序流,保留键。
$stream->asort(callable $comparator = null)
如果没有提供比较器,可迭代表达式源中的元素必须是可比较的。
use IterTools\Stream; $worldPopulations = [ 'China' => 1_439_323_776, 'India' => 1_380_004_385, 'Indonesia' => 273_523_615, 'USA' => 331_002_651, ]; $result = Stream::of($worldPopulations) ->filter(fn ($pop) => $pop > 300_000_000) ->asort() ->toAssociativeArray(); // USA => 331_002_651, // India => 1_380_004_385, // China => 1_439_323_776,
与...
返回一个流,将额外的源一起连接到单个连续流中。
$stream->chainWith(iterable ...$iterables): Stream
use IterTools\Stream; $input = [1, 2, 3]; $result = Stream::of($input) ->chainWith([4, 5, 6]) ->chainWith([7, 8, 9]) ->toArray(); // 1, 2, 3, 4, 5, 6, 7, 8, 9
Compress
通过过滤掉未选择的数据压缩到新的流。
$stream->compress(iterable $selectors): Stream
选择器指示哪些数据。真值选择项目。假值过滤掉数据。
use IterTools\Stream; $input = [1, 2, 3]; $result = Stream::of($input) ->compress([0, 1, 1]) ->toArray(); // 2, 3
Compress Associative
通过过滤掉未选择的关键字压缩到新的流。
$stream->compressAssociative(array $keys): Stream
- 仅支持标准 PHP 数组/迭代器键(字符串,整数)。
use IterTools\Stream; $starWarsEpisodes = [ 'I' => 'The Phantom Menace', 'II' => 'Attack of the Clones', 'III' => 'Revenge of the Sith', 'IV' => 'A New Hope', 'V' => 'The Empire Strikes Back', 'VI' => 'Return of the Jedi', 'VII' => 'The Force Awakens', 'VIII' => 'The Last Jedi', 'IX' => 'The Rise of Skywalker', ]; $sequelTrilogyNumbers = ['VII', 'VIII', 'IX']; $sequelTrilogy = Stream::of($starWarsEpisodes) ->compressAssociative($sequelTrilogyNumbers) ->toAssociativeArray(); // 'VII' => 'The Force Awakens', // 'VIII' => 'The Last Jedi', // 'IX' => 'The Rise of Skywalker',
Chunkwise
返回一个流,它由流中的元素块组成。
$stream->chunkwise(int $chunkSize): Stream
块大小必须至少为 1。
use IterTools\Stream; $friends = ['Ross', 'Rachel', 'Chandler', 'Monica', 'Joey']; $result = Stream::of($friends) ->chunkwise(2) ->toArray(); // ['Ross', 'Rachel'], ['Chandler', 'Monica'], ['Joey']
Chunkwise Overlap
返回一个流,它由流中的重叠元素块组成。
$stream->chunkwiseOverlap(int $chunkSize, int $overlapSize, bool $includeIncompleteTail = true): Stream
- 块大小必须至少为 1。
- 重叠大小必须小于块大小。
use IterTools\Stream; $numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9]; $result = Stream::of($friends) ->chunkwiseOverlap(3, 1) ->toArray() // [1, 2, 3], [3, 4, 5], [5, 6, 7], [7, 8, 9]
区分
返回一个流,它过滤掉流中的元素,仅返回不同的元素。
$stream->distinct(bool $strict = true): Stream
默认为严格类型比较。将严格设置为 false 以进行类型强制比较。
use IterTools\Stream; $input = [1, 2, 1, 2, 3, 3, '1', '1', '2', '3']; $stream = Stream::of($input) ->distinct() ->toArray(); // 1, 2, 3, '1', '2', '3' $stream = Stream::of($input) ->distinct(false) ->toArray(); // 1, 2, 3
根据函数区分
返回一个流,它过滤掉流中的元素,仅返回根据自定义比较函数不同的元素。
$stream->distinctBy(callable $compareBy): Stream
use IterTools\Stream; $streetFighterConsoleReleases = [ ['id' => '112233', 'name' => 'Street Fighter 3 3rd Strike', 'console' => 'Dreamcast'], ['id' => '223344', 'name' => 'Street Fighter 3 3rd Strike', 'console' => 'PS4'], ['id' => '334455', 'name' => 'Street Fighter 3 3rd Strike', 'console' => 'PS5'], ['id' => '445566', 'name' => 'Street Fighter VI', 'console' => 'PS4'], ['id' => '556677', 'name' => 'Street Fighter VI', 'console' => 'PS5'], ['id' => '667799', 'name' => 'Street Fighter VI', 'console' => 'PC'], ]; $stream = Stream::of($streetFighterConsoleReleases) ->distinctBy(fn ($sfTitle) => $sfTitle['name']) ->toArray(); // Contains one SF3 3rd Strike entry and one SFVI entry
Drop While
当谓词函数为真时,从流中删除元素。
$stream->dropWhile(callable $predicate): Stream
一旦谓词函数返回 false,则返回所有剩余元素。
use IterTools\Stream; $input = [1, 2, 3, 4, 5] $result = Stream::of($input) ->dropWhile(fn ($value) => $value < 3) ->toArray(); // 3, 4, 5
过滤器
从流中过滤掉元素,仅保留谓词函数为真的元素。
$stream->filter(callable $predicate): Stream
use IterTools\Stream; $input = [1, -1, 2, -2, 3, -3]; $result = Stream::of($input) ->filter(fn ($value) => $value > 0) ->toArray(); // 1, 2, 3
筛选 True
从流中过滤掉元素,仅保留真值元素。
$stream->filterTrue(): Stream
use IterTools\Stream; $input = [0, 1, 2, 3, 0, 4]; $result = Stream::of($input) ->filterTrue() ->toArray(); // 1, 2, 3, 4
筛选 False
从流中过滤掉元素,仅保留假值元素。
$stream->filterFalse(): Stream
use IterTools\Stream; $input = [0, 1, 2, 3, 0, 4]; $result = Stream::of($input) ->filterFalse() ->toArray(); // 0, 0
筛选键
从流中过滤掉元素,仅保留键上谓词函数为真的元素。
$stream->filterKeys(callable $filter): Stream
$olympics = [ 2000 => 'Sydney', 2002 => 'Salt Lake City', 2004 => 'Athens', 2006 => 'Turin', 2008 => 'Beijing', 2010 => 'Vancouver', 2012 => 'London', 2014 => 'Sochi', 2016 => 'Rio de Janeiro', 2018 => 'Pyeongchang', 2020 => 'Tokyo', 2022 => 'Beijing', ]; $winterFilter = fn ($year) => $year % 4 === 2; $result = Stream::of($olympics) ->filterKeys($winterFilter) ->toAssociativeArray(); } // 2002 => Salt Lake City // 2006 => Turin // 2010 => Vancouver // 2014 => Sochi // 2018 => Pyeongchang // 2022 => Beijing
扁平映射
将函数映射到流元素上,并展平结果。
$stream->flatMap(callable $mapper): Stream
$data = [1, 2, 3, 4, 5]; $mapper fn ($item) => ($item % 2 === 0) ? [$item, $item] : $item; $result = Stream::of($data) ->flatMap($mapper) ->toArray(); // [1, 2, 2, 3, 4, 4, 5]
展开
展平多维流。
$stream->flatten(int $dimensions = 1): Stream
$data = [1, [2, 3], [4, 5]]; $result = Stream::of($data) ->flatten($mapper) ->toArray(); // [1, 2, 3, 4, 5]
频率
流元素的频率分布。
$stream->frequencies(bool $strict = true): Stream
use IterTools\Stream; $grades = ['A', 'A', 'B', 'B', 'B', 'C']; $result = Stream::of($grades) ->frequencies() ->toAssociativeArray(); // ['A' => 2, 'B' => 3, 'C' => 1]
按组
根据公共数据元素分组返回流。
$stream->groupBy(callable $groupKeyFunction, callable $itemKeyFunction = null): Stream
- $groupKeyFunction 决定了分组元素的关键字。
- 可选的 $itemKeyFunction 允许在每组成员中自定义索引。
use IterTools\Stream; $input = [1, -1, 2, -2, 3, -3]; $groups = Stream::of($input) ->groupBy(fn ($item) => $item > 0 ? 'positive' : 'negative'); foreach ($groups as $group => $item) { // 'positive' => [1, 2, 3], 'negative' => [-1, -2, -3] }
无限循环
返回一个流,无限顺序地遍历流的元素。
$stream->infiniteCycle(): Stream
use IterTools\Stream; $input = [1, 2, 3]; $result = Stream::of($input) ->infiniteCycle() ->print(); // 1, 2, 3, 1, 2, 3, ...
与交集
返回与输入可迭代对象交集的流。
$stream->intersectionWith(iterable ...$iterables): Stream
use IterTools\Stream; $numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9]; $numerics = ['1', '2', 3, 4, 5, 6, 7, '8', '9']; $oddNumbers = [1, 3, 5, 7, 9, 11]; $stream = Stream::of($numbers) ->intersectionWith($numerics, $oddNumbers) ->toArray(); // 3, 5, 7
强制类型转换与交集
使用类型强制转换返回与输入可迭代对象交集的流。
$stream->intersectionCoerciveWith(iterable ...$iterables): Stream
use IterTools\Stream; $languages = ['php', 'python', 'c++', 'java', 'c#', 'javascript', 'typescript']; $scriptLanguages = ['php', 'python', 'javascript', 'typescript']; $supportsInterfaces = ['php', 'java', 'c#', 'typescript']; $stream = Stream::of($languages) ->intersectionCoerciveWith($scriptLanguages, $supportsInterfaces) ->toArray(); // 'php', 'typescript'
限制
返回一个达到限制的流。
如果达到限制,则停止迭代,即使还有更多数据可用。
$stream->limit(int $limit): Stream
Use IterTools\Single; $matrixMovies = ['The Matrix', 'The Matrix Reloaded', 'The Matrix Revolutions', 'The Matrix Resurrections']; $limit = 1; $goodMovies = Stream::of($matrixMovies) ->limit($limit) ->toArray(); // 'The Matrix' (and nothing else)
映射
返回一个映射到流每个元素的函数结果的流。
$stream->map(callable $function): Stream
use IterTools\Stream; $grades = [100, 95, 98, 89, 100]; $result = Stream::of($grades) ->map(fn ($grade) => $grade === 100 ? 'A' : 'F') ->toArray(); // A, F, F, F, A
成对
返回一个由流元素对组成的流。
$stream->pairwise(): Stream
如果给定集合包含少于2个元素,则返回空流。
use IterTools\Stream; $input = [1, 2, 3, 4, 5]; $stream = Stream::of($input) ->pairwise() ->toArray(); // [1, 2], [2, 3], [3, 4], [4, 5]
部分交集与
返回与输入可迭代对象部分交集的流。
$stream->partialIntersectionWith(int $minIntersectionCount, iterable ...$iterables): Stream
use IterTools\Stream; $numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9]; $numerics = ['1', '2', 3, 4, 5, 6, 7, '8', '9']; $oddNumbers = [1, 3, 5, 7, 9, 11]; $stream = Stream::of($numbers) ->partialIntersectionWith($numerics, $oddNumbers) ->toArray(); // 1, 3, 4, 5, 6, 7, 9
部分强制类型转换与交集
使用类型强制转换返回与输入可迭代对象部分交集的流。
$stream->partialIntersectionCoerciveWith(int $minIntersectionCount, iterable ...$iterables): Stream
use IterTools\Stream; $languages = ['php', 'python', 'c++', 'java', 'c#', 'javascript', 'typescript']; $scriptLanguages = ['php', 'python', 'javascript', 'typescript']; $supportsInterfaces = ['php', 'java', 'c#', 'typescript']; $stream = Stream::of($languages) ->partialIntersectionCoerciveWith(2, $scriptLanguages, $supportsInterfaces) ->toArray(); // 'php', 'python', 'java', 'typescript', 'c#', 'javascript'
重索引
根据键索引函数重新索引键值元素的新流。
$stream->reindex(callable $indexer): Stream
use IterTools\Stream; $data = [ [ 'title' => 'Star Wars: Episode IV – A New Hope', 'episode' => 'IV', 'year' => 1977, ], [ 'title' => 'Star Wars: Episode V – The Empire Strikes Back', 'episode' => 'V', 'year' => 1980, ], [ 'title' => 'Star Wars: Episode VI – Return of the Jedi', 'episode' => 'VI', 'year' => 1983, ], ]; $reindexFunc = fn (array $swFilm) => $swFilm['episode']; $reindexResult = Stream::of($data) ->reindex($reindexFunc) ->toAssociativeArray(); // [ // 'IV' => [ // 'title' => 'Star Wars: Episode IV – A New Hope', // 'episode' => 'IV', // 'year' => 1977, // ], // 'V' => [ // 'title' => 'Star Wars: Episode V – The Empire Strikes Back', // 'episode' => 'V', // 'year' => 1980, // ], // 'VI' => [ // 'title' => 'Star Wars: Episode VI – Return of the Jedi', // 'episode' => 'VI', // 'year' => 1983, // ], // ]
相对频率
流元素的相对频率分布。
$stream->relativeFrequencies(bool $strict = true): Stream
use IterTools\Stream; $grades = ['A', 'A', 'B', 'B', 'B', 'C']; $result = Stream::of($grades) ->relativeFrequencies() ->toAssociativeArray(); // A => 0.33, B => 0.5, C => 0.166
反转
反转流元素。
$stream->reverse(): Stream
use IterTools\Stream; $words = ['are', 'you', 'as' ,'bored', 'as', 'I', 'am']; $reversed = Stream::of($words) ->reverse() ->toString(' '); // am I as bored as you are
移动平均
返回一个在流上累计运行平均值(平均值)的流。
$stream->runningAverage(int|float|null $initialValue = null): Stream
use IterTools\Stream; $input = [1, 3, 5]; $result = Stream::of($input) ->runningAverage() ->toArray(); // 1, 2, 3
运行差分
返回一个在流上累计运行差值的流。
$stream->runningDifference(int|float|null $initialValue = null): Stream
use IterTools\Stream; $input = [1, 2, 3, 4, 5]; $result = Stream::of($input) ->runningDifference() ->toArray(); // -1, -3, -6, -10, -15
运行最大值
返回一个在流上累计运行最大值的流。
$stream->runningMax(int|float|null $initialValue = null): Stream
use IterTools\Stream; $input = [1, -1, 2, -2, 3, -3]; $result = Stream::of($input) ->runningMax() ->toArray(); // 1, 1, 2, 2, 3, 3
运行最小值
返回一个在流上累计运行最小值的流。
$stream->runningMin(int|float|null $initialValue = null): Stream
use IterTools\Stream; $input = [1, -1, 2, -2, 3, -3]; $result = Stream::of($input) ->runningMin() ->toArray(); // 1, -1, -1, -2, -2, -3
运行乘积
返回一个在流上累计运行乘积的流。
$stream->runningProduct(int|float|null $initialValue = null): Stream
use IterTools\Stream; $input = [1, 2, 3, 4, 5]; $result = Stream::of($input) ->runningProduct() ->toArray(); // 1, 2, 6, 24, 120
运行总计
返回一个在流上累计运行总和的流。
$stream->runningTotal(int|float|null $initialValue = null): Stream
use IterTools\Stream; $input = [1, 2, 3, 4, 5]; $result = Stream::of($input) ->runningTotal() ->toArray(); // 1, 3, 6, 10, 15
跳过
跳过流中的某些元素。
$stream->skip(int $count, int $offset = 0): Stream
use IterTools\Stream; $movies = [ 'The Phantom Menace', 'Attack of the Clones', 'Revenge of the Sith', 'A New Hope', 'The Empire Strikes Back', 'Return of the Jedi', 'The Force Awakens', 'The Last Jedi', 'The Rise of Skywalker' ]; $onlyTheBest = Stream::of($movies) ->skip(3) ->skip(3, 3) ->toArray(); // 'A New Hope', 'The Empire Strikes Back', 'Return of the Jedi'
切片
提取流的片段。
$stream->slice(int $start = 0, int $count = null, int $step = 1)
use IterTools\Stream; $olympics = [1992, 1994, 1996, 1998, 2000, 2002, 2004, 2006, 2008, 2010, 2012, 2014, 2016, 2018, 2020, 2022]; $summerOlympics = Stream::of($olympics) ->slice(0, 8, 2) ->toArray(); // [1992, 1996, 2000, 2004, 2008, 2012, 2016, 2020]
Sort
对流进行排序。
$stream->sort(callable $comparator = null)
如果没有提供比较器,可迭代表达式源中的元素必须是可比较的。
use IterTools\Stream; $input = [3, 4, 5, 9, 8, 7, 1, 6, 2]; $result = Stream::of($input) ->sort() ->toArray(); // 1, 2, 3, 4, 5, 6, 7, 8, 9
与对称差分
返回与给定可迭代对象对称差分的流。
$stream->symmetricDifferenceWith(iterable ...$iterables): Stream
注意:如果输入的可迭代对象产生重复项,则适用多重集合交集规则。
use IterTools\Stream; $a = [1, 2, 3, 4, 7]; $b = ['1', 2, 3, 5, 8]; $c = [1, 2, 3, 6, 9]; $stream = Stream::of($a) ->symmetricDifferenceWith($b, $c) ->toArray(); // '1', 4, 5, 6, 7, 8, 9
对称差强制与
使用类型强制返回流与给定可迭代对象之间对称差的流。
$stream->symmetricDifferenceCoerciveWith(iterable ...$iterables): Stream
注意:如果输入的可迭代对象产生重复项,则适用多重集合交集规则。
use IterTools\Stream; $a = [1, 2, 3, 4, 7]; $b = ['1', 2, 3, 5, 8]; $c = [1, 2, 3, 6, 9]; $stream = Stream::of($a) ->symmetricDifferenceCoerciveWith($b, $c) ->toArray(); // 4, 5, 6, 7, 8, 9
Take While
只要谓词为真,就保留流中的元素。
$stream->takeWhile(callable $predicate): Stream
如果没有提供谓词,则使用数据的布尔值。
use IterTools\Stream; $input = [1, -1, 2, -2, 3, -3]; $result = Stream::of($input) ->takeWhile(fn ($value) => abs($value) < 3) ->toArray(); // 1, -1, 2, -2
与联合
返回由流和输入的可迭代对象组成的联合流。
$stream->unionWith(iterable ...$iterables): Stream
注意:如果输入的可迭代对象产生重复项,则适用多重集合联合规则。
use IterTools\Stream; $input = [1, 2, 3]; $stream = Stream::of($input) ->unionWith([3, 4, 5, 6]) ->toArray(); // [1, 2, 3, 4, 5, 6]
联合强制与
使用类型强制返回由流和输入的可迭代对象组成的联合流。
$stream->unionCoerciveWith(iterable ...$iterables): Stream
注意:如果输入的可迭代对象产生重复项,则适用多重集合联合规则。
use IterTools\Stream; $input = [1, 2, 3]; $stream = Stream::of($input) ->unionCoerciveWith(['3', 4, 5, 6]) ->toArray(); // [1, 2, 3, 4, 5, 6]
与压缩
返回由多个同时流出的可迭代集合组成的流。
$stream->zipWith(iterable ...$iterables): Stream
对于不等长的迭代,迭代将在最短的迭代对象耗尽时停止。
use IterTools\Stream; $input = [1, 2, 3]; $stream = Stream::of($input) ->zipWith([4, 5, 6]) ->zipWith([7, 8, 9]) ->toArray(); // [1, 4, 7], [2, 5, 8], [3, 6, 9]
用默认填充值压缩
返回由多个可迭代集合组成的流,如果不等长则使用默认填充值。
$stream->zipFilledWith(mixed $default, iterable ...$iterables): Stream
use IterTools\Stream; $input = [1, 2, 3]; $stream = Stream::of($input) ->zipFilledWith('?', ['A', 'B']); foreach ($stream as $zipped) { // [1, A], [2, B], [3, ?] }
与等长压缩
返回由等长可迭代集合组成的流,同时流出。
$stream->zipEqualWith(iterable ...$iterables): Stream
与Stream::zipWith()
方法类似,但如果长度不等则抛出\LengthException,即至少有一个迭代器在其他迭代器之前结束。
use IterTools\Stream; $input = [1, 2, 3]; $stream = Stream::of($input) ->zipEqualWith([4, 5, 6]) ->zipEqualWith([7, 8, 9]); foreach ($stream as $zipped) { // [1, 4, 7], [2, 5, 8], [3, 6, 9] }
与最长压缩
返回由多个同时流出的可迭代集合组成的流。
$stream->zipLongestWith(iterable ...$iterables): Stream
- 迭代将继续,直到最长的迭代对象耗尽。
- 对于不等长的迭代,耗尽的迭代对象将在剩余的迭代中产生null。
use IterTools\Stream; $input = [1, 2, 3, 4, 5]; $stream = Stream::of($input) ->zipLongestWith([4, 5, 6]) ->zipLongestWith([7, 8, 9, 10]); foreach ($stream as $zipped) { // [1, 4, 7], [2, 5, 8], [3, 6, 9], [4, null, 10], [null, null, 5] }
流终端操作
流摘要终端操作
全部匹配
如果所有元素都匹配谓词函数,则返回 true。
$stream->allMatch(callable $predicate): bool
use IterTools\Summary; $finalFantasyNumbers = [4, 5, 6]; $isOnSuperNintendo = fn ($ff) => $ff >= 4 && $ff <= 6; $boolean = Stream::of($finalFantasyNumbers) ->allMatch($isOnSuperNintendo); // true
全部唯一
如果所有元素都是唯一的,则返回 true。
$stream->allUnique(bool $strict = true): bool
默认为严格类型比较。将严格设置为 false 以进行类型强制比较。
use IterTools\Summary; $items = ['fingerprints', 'snowflakes', 'eyes', 'DNA'] $boolean = Stream::of($items) ->allUnique(); // true
任意匹配
如果任何元素匹配谓词函数,则返回 true。
$stream->anyMatch(callable $predicate): bool
use IterTools\Summary; $answers = ['fish', 'towel', 42, "don't panic"]; $isUltimateAnswer = fn ($a) => a == 42; $boolean = Stream::of($answers) ->anyMatch($answers, $isUltimateAnswer); // true
与排列相同
如果所有迭代对象都与流是排列,则返回true。
$stream->arePermutationsWith(...$iterables): bool
use IterTools\Summary; $rite = ['r', 'i', 't', 'e']; $reit = ['r', 'e', 'i', 't']; $tier = ['t', 'i', 'e', 'r']; $tire = ['t', 'i', 'r', 'e']; $trie = ['t', 'r', 'i', 'e']; $boolean = Stream::of(['i', 't', 'e', 'r']) ->arePermutationsWith($rite, $reit, $tier, $tire, $trie); // true
与排列强制相同
如果所有迭代对象都与流是排列,并且使用类型强制,则返回true。
$stream->arePermutationsCoerciveWith(...$iterables): bool
use IterTools\Summary; $set2 = [2.0, '1', 3]; $set3 = [3, 2, 1]; $boolean = Stream::of([1, 2.0, '3']) ->arePermutationsCoerciveWith($set2, $set3); // true
正好 N 个
如果根据谓词函数正好有 n 个元素为 true,则返回 true。
- 谓词是可选的。
- 默认谓词是每个项的布尔值。
$stream->exactlyN(int $n, callable $predicate = null): bool
use IterTools\Summary; $twoTruthsAndALie = [true, true, false]; $n = 2; $boolean = Stream::of($twoTruthsAndALie)->exactlyN($n); // true
是否为空
如果流为空且没有项,则返回true。
$stream->isEmpty(): bool
use IterTools\Summary; $numbers = [0, 1, 2, 3, 4, 5]; $filterFunc = fn ($x) => $x > 10; $boolean = Stream::($numbers) ->filter($filterFunc) ->isEmpty(); // true
是否已分割
如果给定集合中满足谓词的所有元素都出现在不满足谓词的所有元素之前,则返回 true。
- 对于空集合或单个项目的集合,返回 true。
- 如果没有提供,默认谓词是每个数据项的布尔值。
$stream->isPartitioned(callable $predicate = null): bool
use IterTools\Summary; $numbers = [0, 2, 4, 1, 3, 5]; $evensBeforeOdds = fn ($item) => $item % 2 === 0; $boolean = Stream::($numbers) ->isPartitioned($evensBeforeOdds); // true
是否已排序
如果可迭代源按升序排序,则返回true;否则返回false。
$stream->isSorted(): bool
可迭代源的项目必须是可比较的。
如果可迭代源为空或只有一个元素,则返回true。
use IterTools\Stream; $input = [1, 2, 3, 4, 5]; $result = Stream::of($input) ->isSorted(); // true $input = [1, 2, 3, 2, 1]; $result = Stream::of($input) ->isSorted(); // false
是否已反转
如果可迭代源按降序排序,则返回true;否则返回false。
$stream->isReversed(): bool
可迭代源的项目必须是可比较的。
如果可迭代源为空或只有一个元素,则返回true。
use IterTools\Stream; $input = [5, 4, 3, 2, 1]; $result = Stream::of($input) ->isReversed(); // true $input = [1, 2, 3, 2, 1]; $result = Stream::of($input) ->isReversed(); // false
没有匹配
如果没有元素匹配谓词函数,则返回 true。
$stream->noneMatch(callable $predicate): bool
use IterTools\Summary; $grades = [45, 50, 61, 0]; $isPassingGrade = fn ($grade) => $grade >= 70; $boolean = Stream::of($grades)->noneMatch($isPassingGrade); // true
与相同
如果可迭代源和所有给定的集合都相同,则返回true。
$stream->sameWith(iterable ...$iterables): bool
对于空的迭代对象列表返回true。
use IterTools\Stream; $input = [1, 2, 3, 4, 5]; $result = Stream::of($input) ->sameWith([1, 2, 3, 4, 5]); // true $result = Stream::of($input) ->sameWith([5, 4, 3, 2, 1]); // false
相同计数与
如果可迭代源和所有给定的集合具有相同的长度,则返回true。
$stream->sameCountWith(iterable ...$iterables): bool
对于空的迭代对象列表返回true。
use IterTools\Stream; $input = [1, 2, 3, 4, 5]; $result = Stream::of($input) ->sameCountWith([5, 4, 3, 2, 1]); // true $result = Stream::of($input) ->sameCountWith([1, 2, 3]); // false
流归约终端操作
转换为平均值
将可迭代源归约为其项目的平均平均值。
$stream->toAverage(): mixed
如果可迭代源为空,则返回null。
use IterTools\Stream; $input = [2, 4, 6, 8]; $result = Stream::of($iterable) ->toAverage(); // 5
转换为计数
将可迭代源归约为其长度。
$stream->toCount(): mixed
use IterTools\Stream; $input = [10, 20, 30, 40, 50]; $result = Stream::of($iterable) ->toCount(); // 5
转换为第一个
将可迭代源归约为其第一个元素。
$stream->toFirst(): 混合类型
如果可迭代源为空,则抛出\LengthException
。
use IterTools\Stream; $input = [10, 20, 30]; $result = Stream::of($input) ->toFirst(); // 10
转换为第一个和最后一个
将可迭代源缩减为其第一个和最后一个元素。
$stream->toFirstAndLast(): array{混合类型, 混合类型}
如果可迭代源为空,则抛出\LengthException
。
use IterTools\Stream; $input = [10, 20, 30]; $result = Stream::of($input) ->toFirstAndLast(); // [10, 30]
转换为最后一个
将可迭代源缩减为其最后一个元素。
$stream->toLast(): 混合类型
如果可迭代源为空,则抛出\LengthException
。
use IterTools\Stream; $input = [10, 20, 30]; $result = Stream::of($input) ->toLast(); // 30
转换为最大值
将可迭代源缩减为其最大值。
$stream->toMax(callable $compareBy = null): 混合类型
- 可选的可调用参数
$compareBy
必须返回可比较的值。 - 如果没有提供
$compareBy
,则给定集合的项必须是可比较的。 - 如果集合为空,则返回 null。
use IterTools\Stream; $input = [1, -1, 2, -2, 3, -3]; $result = Stream::of($iterable) ->toMax(); // 3
转换为最小值
将可迭代源缩减为其最小值。
$stream->toMin(callable $compareBy = null): 混合类型
- 可选的可调用参数
$compareBy
必须返回可比较的值。 - 如果没有提供
$compareBy
,则给定集合的项必须是可比较的。 - 如果集合为空,则返回 null。
use IterTools\Stream; $input = [1, -1, 2, -2, 3, -3]; $result = Stream::of($iterable) ->toMin(); // -3
转换为最大最小值
将流缩减为其上界和下界(最大值和最小值)的数组。
$stream->toMinMax(callable $compareBy = null): array
- 可选的可调用参数
$compareBy
必须返回可比较的值。 - 如果没有提供
$compareBy
,则给定集合的项必须是可比较的。 - 如果给定的集合为空,则返回
[null, null]
。
use IterTools\Stream; $numbers = [1, 2, 7, -1, -2, -3]; [$min, $max] = Stream::of($numbers) ->toMinMax(); // [-3, 7]
转换为第 N 个
将流缩减为其第n个位置上的值。
$stream->toNth(int $position): 混合类型
如果可迭代源为空,则返回null。
use IterTools\Stream; $lotrMovies = ['The Fellowship of the Ring', 'The Two Towers', 'The Return of the King']; $result = Stream::of($lotrMovies) ->toNth(2); // The Return of the King
转换为乘积
将流缩减为其项的乘积。
$stream->toProduct(): 混合类型
如果可迭代源为空,则返回null。
use IterTools\Stream; $input = [1, 2, 3, 4, 5]; $result = Stream::of($iterable) ->toProduct(); // 120
到随机值
将流缩减为其内部随机值。
$stream->toRandomValue(): 混合类型
use IterTools\Stream; $rpsHands = ['rock', 'paper', 'scissors'] $range = Stream::of($numbers) ->map('strtoupper') ->toRandomValue(); // e.g., rock
到范围
将流缩减为其范围(最大值和最小值之差)。
$stream->toRange(): int|float
如果可迭代表达式为空,则返回 0
。
use IterTools\Stream; $grades = [100, 90, 80, 85, 95]; $range = Stream::of($numbers) ->toRange(); // 20
到字符串
将所有元素缩减为一个字符串连接。
- 在项目之间插入的可选分隔符。
- 字符串前可选的前缀。
- 字符串后可选的后缀。
$stream->toString(string $separator = '', string $prefix = '', string $suffix = ''): string
use IterTools\Stream; $words = ['IterTools', 'PHP', 'v1.0']; $string = Stream::of($words)->toString($words); // IterToolsPHPv1.0 $string = Stream::of($words)->toString($words, '-'); // IterTools-PHP-v1.0 $string = Stream::of($words)->toString($words, '-', 'Library: '); // Library: IterTools-PHP-v1.0 $string = Stream::of($words)->toString($words, '-', 'Library: ', '!'); // Library: IterTools-PHP-v1.0!
到总和
将可迭代源缩减为其项的总和。
$stream->toSum(): 混合类型
use IterTools\Stream; $input = [1, 2, 3, 4, 5]; $result = Stream::of($iterable) ->toSum(); // 15
到值
类似于array_reduce()函数缩减可迭代源。
但与array_reduce()
不同,它适用于所有iterable
类型。
$stream->toValue(callable $reducer, mixed $initialValue): 混合类型
use IterTools\Stream; $input = [1, 2, 3, 4, 5]; $result = Stream::of($iterable) ->toValue(fn ($carry, $item) => $carry + $item); // 15
转换终端操作
转为数组
返回流元素的数组。
$stream->toArray(): array
use IterTools\Stream; $array = Stream::of([1, 1, 2, 2, 3, 4, 5]) ->distinct() ->map(fn ($x) => $x**2) ->toArray(); // [1, 4, 9, 16, 25]
转为关联数组
返回流元素的键值映射。
$stream->toAssociativeArray(callable $keyFunc, callable $valueFunc): array
use IterTools\Stream; $keyFunc $array = Stream::of(['message 1', 'message 2', 'message 3']) ->map('strtoupper') ->toAssociativeArray( fn ($s) => \md5($s), fn ($s) => $s ); // [3b3f2272b3b904d342b2d0df2bf31ed4 => MESSAGE 1, 43638d919cfb8ea31979880f1a2bb146 => MESSAGE 2, ... ]
分叉
返回几个独立(重复)的流。
$stream->tee(int $count): array
use IterTools\Transform; $daysOfWeek = ['Mon', 'Tues', 'Wed', 'Thurs', 'Fri', 'Sat', 'Sun']; $count = 3; [$week1Stream, $week2Stream, $week3Stream] = Stream::of($daysOfWeek) ->tee($count); // Each $weekStream contains ['Mon', 'Tues', 'Wed', 'Thurs', 'Fri', 'Sat', 'Sun']
副作用终端操作
调用 For Each
通过可调用函数对流中的每个项目执行操作。
$stream->callForEach(callable $function): void
use IterTools\Stream; $languages = ['PHP', 'Python', 'Java', 'Go']; $mascots = ['elephant', 'snake', 'bean', 'gopher']; $zipPrinter = fn ($zipped) => print("{$zipped[0]}'s mascot: {$zipped[1]}"); Stream::of($languages) ->zipWith($mascots) ->callForEach($zipPrinter); // PHP's mascot: elephant // Python's mascot: snake // ...
打印
打印流中的每个项目。
- 项目必须是可打印的。
$stream->print(string $separator = '', string $prefix = '', string $suffix = ''): void
use IterTools\Stream; $words = ['IterTools', 'PHP', 'v1.0']; Stream::of($words)->print(); // IterToolsPHPv1.0 Stream::of($words)->print('-'); // IterTools-PHP-v1.0 Stream::of($words)->print('-', 'Library: '); // Library: IterTools-PHP-v1.0 Stream::of($words)->print('-', 'Library: ', '!'); // Library: IterTools-PHP-v1.0!
换行打印
将流中的每个项目打印到单独的一行。
- 项目必须是可打印的。
$stream->println(): void
use IterTools\Stream; $words = ['IterTools', 'PHP', 'v1.0']; Stream::of($words)->printLn(); // IterTools // PHP // v1.0
转换为CSV文件
将流的内容写入CSV文件。
$stream->toCsvFile(resource $fileHandle, array $header = null, string 'separator = ',', string $enclosure = '"', string $escape = '\\'): void
use IterTools\Stream; $starWarsMovies = [ ['Star Wars: Episode IV – A New Hope', 'IV', 1977], ['Star Wars: Episode V – The Empire Strikes Back', 'V', 1980], ['Star Wars: Episode VI – Return of the Jedi', 'VI', 1983], ]; $header = ['title', 'episode', 'year']; Stream::of($data) ->toCsvFile($fh, $header); // title,episode,year // "Star Wars: Episode IV – A New Hope",IV,1977 // "Star Wars: Episode V – The Empire Strikes Back",V,1980 // "Star Wars: Episode VI – Return of the Jedi",VI,1983
转换为文件
将流的内容写入文件。
$stream->toFile(resource $fileHandle, string $newLineSeparator = \PHP_EOL, string $header = null, string $footer = null): void
use IterTools\Stream; $data = ['item1', 'item2', 'item3']; $header = '<ul>'; $footer = '</ul>'; Stream::of($data) ->map(fn ($item) => " <li>$item</li>") ->toFile($fh, \PHP_EOL, $header, $footer); // <ul> // <li>item1</li> // <li>item2</li> // <li>item3</li> // </ul>
流调试操作
预览
在其他Stream操作之间预览每个元素,执行某些操作而不修改流。
$stream->peek(callable $callback): Stream
use IterTools\Stream; $logger = new SimpleLog\Logger('/tmp/log.txt', 'iterTools'); Stream::of(['some', 'items']) ->map('strtoupper') ->peek(fn ($x) => $logger->info($x)) ->foreach($someComplexCallable);
预览流
在其他Stream操作之间预览整个流,执行某些操作而不修改流。
$stream->peekStream(callable $callback): Stream
use IterTools\Stream; $logger = new SimpleLog\Logger('/tmp/log.txt', 'iterTools'); Stream::of(['some', 'items']) ->map('strtoupper') ->peekStream(fn ($stream) => $logger->info($stream)) ->foreach($someComplexCallable);
预览打印
在其他Stream操作之间预览每个元素,打印每个项目而不修改流。
$stream->peekPrint(string $separator = '', string $prefix = '', string $suffix = ''): void
use IterTools\Stream; Stream::of(['some', 'items']) ->map('strtoupper') ->peekPrint() ->foreach($someComplexCallable);
预览打印R
在其他Stream操作之间预览每个元素,使用print_r
打印每个项目而不修改流。
$stream->peekPrintR(callable $callback): void
use IterTools\Stream; Stream::of(['some', 'items']) ->map('strtoupper') ->peekPrintR() ->foreach($someComplexCallable);
打印R
print_r
流中的每个项目。
$stream->printR(): void
use IterTools\Stream; $items = [$string, $array, $object]; Stream::of($words)->printR(); // print_r output
变量转储
var_dump
流中的每个项目。
$stream->varDump(): void
use IterTools\Stream; $items = [$string, $array, $object]; Stream::of($words)->varDump(); // var_dump output
组合
IterTools可以组合在一起创建新的可迭代组合。
字符串拼接
use IterTools\Multi; use IterTools\Single; $letters = 'ABCDEFGHI'; $numbers = '123456789'; foreach (Multi::zip(Single::string($letters), Single::string($numbers)) as [$letter, $number]) { $battleshipMove = new BattleshipMove($letter, $number) } // A1, B2, C3
链式字符串
use IterTools\Multi; use IterTools\Single; $letters = 'abc'; $numbers = '123'; foreach (Multi::chain(Single::string($letters), Single::string($numbers)) as $character) { print($character); } // a, b, c, 1, 2, 3
严格和强制类型
当有选择时,默认将执行严格的类型比较
- 标量:通过类型严格比较
- 对象:始终将不同实例视为彼此不相等
- 数组:比较序列化
当可用的类型强制(非严格类型)通过可选标志启用时
- 标量:通过类型摆弄比较值
- 对象:比较序列化
- 数组:比较序列化
标准
IterTools PHP 符合以下标准
- PSR-1 - 基础编码标准 (http://www.php-fig.org/psr/psr-1/)
- PSR-4 - 自动加载器 (http://www.php-fig.org/psr/psr-4/)
- PSR-12 - 扩展编码风格指南 (http://www.php-fig.org/psr/psr-12/)
许可证
IterTools PHP 采用 MIT 许可证授权。
其他语言的类似库
IterTools 的功能不仅限于 PHP 和 Python。其他语言也有类似的库。在其他语言中工作时,也可以使用熟悉的功能。