gielfeldt / iterators
各种迭代器。
Requires
- php: >=7.0.0
Requires (Dev)
- mikey179/vfsstream: ^1.6
- phpunit/phpunit: ^6
This package is not auto-updated.
Last update: 2024-09-19 12:31:50 UTC
README
安装
composer require gielfeldt/iterators
迭代器
这个库包含了一系列各种迭代器,我主要是为了更好地了解PHP中的迭代器而编写的。其中一些可能有用,而另一些可能很愚蠢。
享受吧!
CachingIterator
缓存迭代器以进行多次迭代。
use Gielfeldt\Iterators\CachingIterator; $input = new \ArrayIterator(range(1, 4)); $input = new \NoRewindIterator($input); $cached = new CachingIterator($input); print_r(iterator_to_array($cached)); print_r(iterator_to_array($cached));
输出
Array
(
[0] => 1
[1] => 2
[2] => 3
[3] => 4
)
Array
(
[0] => 1
[1] => 2
[2] => 3
[3] => 4
)
ChecksumIterator
为迭代器生成校验和,可以是每次迭代或整个数据集。
use Gielfeldt\Iterators\ChecksumIterator; $input = new \ArrayIterator([ ['key1' => 'value1'], ['key2' => 'value2'], ['key3' => 'value3'], ]); $iterator = new ChecksumIterator($input, 'md5'); foreach ($iterator as $key => $value) { print "$key => $value\n"; } var_dump($iterator->getChecksum()); var_dump((string) $iterator);
输出
0 => e2e517365ffe6fedd279364e3fa74786
1 => f0a0db0fc9abe193b21fd657fe678884
2 => c04f606bb5bba82282dfa93edb59c6ee
string(32) "4fd19adc845da6fdd9c7c394f4626bac"
string(32) "4fd19adc845da6fdd9c7c394f4626bac"
ChunkIterator
将迭代器分割成迭代器的块。
use Gielfeldt\Iterators\ChunkIterator; use Gielfeldt\Iterators\AtomicTempFileObject; // Split a file into multiple files of a 100 lines each. $file = new \SplFileObject('inputfile'); foreach (new ChunkIterator($file, 100) as $i => $lines) { AtomicTempFileObject::file_put_contents("outputfile.part.$i", implode("", iterator_to_array($lines))); }
CloningIterator
克隆迭代中的每个值。
use Gielfeldt\Iterators\CloningIterator; $object1 = (object) ['value' => 'test1']; $object2 = (object) ['value' => 'test2']; $object3 = (object) ['value' => 'test3']; $input = new \ArrayIterator([$object1, $object2, $object3]); $iterator = new CloningIterator($input); $cloned = iterator_to_array($iterator); $object1->value = 'MODIFIED'; var_dump(iterator_to_array($input)); var_dump($cloned);
输出
array(3) {
[0] =>
class stdClass#2 (1) {
public $value =>
string(8) "MODIFIED"
}
[1] =>
class stdClass#3 (1) {
public $value =>
string(5) "test2"
}
[2] =>
class stdClass#4 (1) {
public $value =>
string(5) "test3"
}
}
array(3) {
[0] =>
class stdClass#9 (1) {
public $value =>
string(5) "test1"
}
[1] =>
class stdClass#10 (1) {
public $value =>
string(5) "test2"
}
[2] =>
class stdClass#11 (1) {
public $value =>
string(5) "test3"
}
}
CombineIterator
类似于array_combine()。然而,迭代器可以有非唯一键。在使用iterator_to_array()时请注意这一点;
use Gielfeldt\Iterators\CombineIterator; $keys = new \ArrayIterator(['key1', 'key2', 'key3', 'key1', 'key2', 'key3']); $values = new \ArrayIterator(['value1', 'value2', 'value3', 'value4', 'value5', 'value6']); $iterator = new CombineIterator($keys, $values); foreach ($iterator as $key => $value) { print "$key => $value\n"; } print_r(iterator_to_array($iterator));
输出
key1 => value1
key2 => value2
key3 => value3
key1 => value4
key2 => value5
key3 => value6
Array
(
[key1] => value4
[key2] => value5
[key3] => value6
)
CountableIterator
通过迭代并计数使其可计数的任何迭代器。
use Gielfeldt\Iterators\CountableIterator; $some_noncountable_iterator = new \IteratorIterator(new \ArrayIterator([1, 2, 3])); $iterator = new CountableIterator($some_noncountable_iterator); var_dump(count($iterator));
输出
int(3)
DiffIterator
比较两个迭代器。类似于array_diff()。可以设置自定义比较函数。
use Gielfeldt\Iterators\DiffIterator; $input1 = new \ArrayIterator(['key1' => 'value1', 'key2' => 'value2', 'key3' => 'value3']); $input2 = new \ArrayIterator(['key11' => 'value1', 'key22' => 'value1', 'key2' => 'value3']); $input3 = new \ArrayIterator(['key1' => 'value2', 'key2' => 'value2', 'key33' => 'value3']); $iterator = new DiffIterator($input1, $input2, $input3); $iterator->setDiff(function ($iterator, $key, $value) { return $iterator->key() == $key && $iterator->current() == $value; }); print_r(iterator_to_array($iterator));
输出
Array
(
[key1] => value1
[key3] => value3
)
FiniteIterator
通过匿名函数为迭代器提供一个结束条件。
use Gielfeldt\Iterators\FiniteIterator; $input = new \ArrayIterator(range(1, 8)); $some = new FiniteIterator($input, function ($iterator) { return $iterator->current() > 5; }); print_r(iterator_to_array($some));
输出
Array
(
[0] => 1
[1] => 2
[2] => 3
[3] => 4
[4] => 5
)
FlipIterator
类似于array_flip()。然而,迭代器可以有非唯一键。在使用iterator_to_array()时请注意这一点;
use Gielfeldt\Iterators\FlipIterator; $input = new \ArrayIterator([ 'key1' => 'value1', 'key2' => 'value2', 'key3' => 'value3', 'key4' => 'value1', 'key5' => 'value2', 'key6' => 'value3', ]); $iterator = new FlipIterator($input); foreach ($iterator as $key => $value) { print "$key => $value\n"; } print_r(iterator_to_array($iterator));
输出
value1 => key1
value2 => key2
value3 => key3
value1 => key4
value2 => key5
value3 => key6
Array
(
[value1] => key4
[value2] => key5
[value3] => key6
)
GlobIterator
类似于\GlobIterator,但支持**
use Gielfeldt\Iterators\GlobIterator; $iterator = new GlobIterator('/tmp/**.log'); var_dump(iterator_to_array($iterator));
输出
array(2) {
'/tmp/one.log' =>
class Gielfeldt\Iterators\GlobIteratorFileInfo#17 (2) {
private $pathName =>
string(20) "/tmp/one.log"
private $fileName =>
string(10) "one.log"
}
'/tmp/somedir/two.log' =>
class Gielfeldt\Iterators\GlobIteratorFileInfo#16 (2) {
private $pathName =>
string(20) "/tmp/somedir/two.log"
private $fileName =>
string(15) "two.log"
}
}
IndexIterator
仅遍历迭代器的某些行。
use Gielfeldt\Iterators\IndexIterator; $input = new \ArrayIterator([ 'test1' => 'val6', 'test2' => 'val5', 'test3' => 'val4', 'test4' => 'val3', 'test5' => 'val2', 'test6' => 'val1', ]); $some = new IndexIterator($input, [2, 3, 5]); print_r(iterator_to_array($some));
输出
Array
(
[test3] => val4
[test4] => val3
[test6] => val1
)
InfiniteIterator
类似于SPL的InfiniteIterator,但提供了getCurrentIteration()方法。
use Gielfeldt\Iterators\InfiniteIterator; use Gielfeldt\Iterators\FiniteIterator; $input = new \ArrayIterator(range(1, 4)); $infinite = new InfiniteIterator($input); $some = new FiniteIterator($infinite, function ($iterator) { return $iterator->getCurrentIteration() >= 2 && $iterator->current() > 2; }); foreach ($some as $k => $v) { print $some->getCurrentIteration() . ": $k => $v\n"; }
输出
0: 0 => 1
0: 1 => 2
0: 2 => 3
0: 3 => 4
1: 0 => 1
1: 1 => 2
1: 2 => 3
1: 3 => 4
2: 0 => 1
2: 1 => 2
InterleaveIterator
交错多个迭代器。
use Gielfeldt\Iterators\InterleaveIterator; $input1 = new \ArrayIterator([ 'key1' => 'value11', 'key2' => 'value12', 'key3' => 'value13', ]); $input2 = new \ArrayIterator([ 'key21' => 'value21', 'key22' => 'value22', 'key23' => 'value23', ]); $input3 = new \ArrayIterator([ 'key1' => 'value31', 'key2' => 'value32', 'key3' => 'value33', ]); $iterator = new InterleaveIterator($input1, $input2, $input3); foreach ($iterator as $key => $value) { print "$key => $value\n"; } print_r(iterator_to_array($iterator));
输出
key1 => value11
key21 => value21
key1 => value31
key2 => value12
key22 => value22
key2 => value32
key3 => value13
key23 => value23
key3 => value33
Array
(
[key1] => value31
[key21] => value21
[key2] => value32
[key22] => value22
[key3] => value33
[key23] => value23
)
IntersectIterator
类似于array_intersect()。可以设置自定义比较函数。
use Gielfeldt\Iterators\IntersectIterator; $input1 = new \ArrayIterator(['key1' => 'value1', 'key2' => 'value2', 'key3' => 'value3']); $input2 = new \ArrayIterator(['key11' => 'value1', 'key1' => 'value1', 'key2' => 'value3']); $input3 = new \ArrayIterator(['key1' => 'value2', 'key2' => 'value2', 'key1' => 'value1']); $iterator = new IntersectIterator($input1, $input2, $input3); $iterator->setDiff(function ($iterator, $key, $value) { return $iterator->key() == $key && $iterator->current() == $value; }); print_r(iterator_to_array($iterator));
输出
Array
(
[key1] => value1
)
TraversableIterator
类似于SPL的IteratorIterator,但有一个更有意义的名字:-)并提供getIndex()方法。
use Gielfeldt\Iterators\TraversableIterator; $keys = range(1, 10); shuffle($keys); $values = range(1, 10); shuffle($values); $input = new \ArrayIterator(array_combine($keys, $values)); $iterator = new TraversableIterator($input); foreach ($iterator as $k => $v) { print $iterator->getIndex() . ": $k => $v\n"; }
输出
0: 1 => 3
1: 4 => 2
2: 9 => 10
3: 3 => 8
4: 2 => 6
5: 5 => 5
6: 8 => 1
7: 10 => 9
8: 6 => 7
9: 7 => 4
KeysIterator
类似于array_keys()。
use Gielfeldt\Iterators\KeysIterator; $input = new \ArrayIterator([ 'key1' => 'value1', 'key2' => 'value2', 'key3' => 'value3', ]); $iterator = new KeysIterator($input); print_r(iterator_to_array($iterator));
输出
Array
(
[0] => key1
[1] => key2
[2] => key3
)
MapIterator
类似于array_map()。
use Gielfeldt\Iterators\MapIterator; $input = new \ArrayIterator([ 'key1' => 'value1', 'key2' => 'value2', 'key3' => 'value3', 'key4' => 'value1', 'key5' => 'value2', 'key6' => 'value3', ]); // Flip keys and values. $iterator = new MapIterator($input, function ($iterator) { return [$iterator->current(), $iterator->key()]; }); foreach ($iterator as $key => $value) { print "$key => $value\n"; } print_r(iterator_to_array($iterator));
输出
value1 => key1
value2 => key2
value3 => key3
value1 => key4
value2 => key5
value3 => key6
Array
(
[value1] => key4
[value2] => key5
[value3] => key6
)
RandomIterator
从可遍历的集合中选择一组随机元素。不适用于只能遍历一次的迭代器。请参阅ReservoirSamplingIterator。
use Gielfeldt\Iterators\RandomIterator; $input = new \ArrayIterator(range(1, 10)); $random = new RandomIterator($input, 4); var_dump(count($random)); print_r(iterator_to_array($random));
输出
int(4)
Array
(
[1] => 2
[6] => 7
[7] => 8
[8] => 9
)
RepeatIterator
重复迭代器n次。
use Gielfeldt\Iterators\RepeatIterator; $input = new \ArrayIterator([ 'key1' => 'value1', 'key2' => 'value2', 'key3' => 'value3', ]); $iterator = new RepeatIterator($input, 3); foreach ($iterator as $key => $value) { print "$key => $value\n"; } print_r(iterator_to_array($iterator));
输出
key1 => value1
key2 => value2
key3 => value3
key1 => value1
key2 => value2
key3 => value3
key1 => value1
key2 => value2
key3 => value3
Array
(
[key1] => value1
[key2] => value2
[key3] => value3
)
ReplaceableIterator
类似于TraversableIterator,但具有setInnerIterator()方法。
use Gielfeldt\Iterators\ReplaceableIterator; $iterator = new ReplaceableIterator(new \ArrayIterator(range(1, 4))); print_r(iterator_to_array($iterator)); $iterator->setInnerIterator(new \ArrayIterator(range(5, 8))); print_r(iterator_to_array($iterator));
输出
Array
(
[0] => 1
[1] => 2
[2] => 3
[3] => 4
)
Array
(
[0] => 5
[1] => 6
[2] => 7
[3] => 8
)
ReservoirSamplingIterator
类似于RandomIterator,但更有效地处理未知大小或只能遍历一次的迭代器。
use Gielfeldt\Iterators\ReservoirSamplingIterator; $input = new \ArrayIterator(range(1, 10)); $input = new \NoRewindIterator($input); $random = new ReservoirSamplingIterator($input, 4); print_r(iterator_to_array($random));
输出
int(4)
Array
(
[1] => 2
[6] => 7
[7] => 8
[8] => 9
)
ShuffleIterator
随机遍历可遍历的集合。
use Gielfeldt\Iterators\ShuffleIterator; $input = new \ArrayIterator(range(1, 10)); $shuffled = new ShuffleIterator($input); print_r(iterator_to_array($shuffled)); print_r(iterator_to_array($shuffled));
输出
Array
(
[1] => 2
[4] => 5
[0] => 1
[9] => 10
[7] => 8
[5] => 6
[2] => 3
[8] => 9
[3] => 4
[6] => 7
)
Array
(
[1] => 2
[9] => 10
[4] => 5
[2] => 3
[5] => 6
[0] => 1
[8] => 9
[3] => 4
[7] => 8
[6] => 7
)
SortIterator
use Gielfeldt\Iterators\SortIterator; $input = new \ArrayIterator([6, 3, 2, 7, 1, 9]); $iterator = new SortIterator($input); print_r(iterator_to_array($iterator)); $input = new \ArrayIterator([6, 3, 2, 7, 1, 9]); $iterator = new SortIterator($input, SortIterator::SORT_DESC); print_r(iterator_to_array($iterator)); $input = new \ArrayIterator([6, 3, 2, 7, 1, 9]); $iterator = new SortIterator($input, SortIterator::SORT_ASC, SortIterator::SORT_REINDEX); print_r(iterator_to_array($iterator)); $input = new \ArrayIterator([6, 3, 2, 7, 1, 9]); $iterator = new SortIterator($input, SortIterator::SORT_ASC, SortIterator::SORT_REINDEX, function ($a, $b) { return -$a->current <=> -$b->current; }); print_r(iterator_to_array($iterator));
输出
Array
(
[4] => 1
[2] => 2
[1] => 3
[0] => 6
[3] => 7
[5] => 9
)
Array
(
[5] => 9
[3] => 7
[0] => 6
[1] => 3
[2] => 2
[4] => 1
)
Array
(
[0] => 1
[1] => 2
[2] => 3
[3] => 6
[4] => 7
[5] => 9
)
Array
(
[0] => 9
[1] => 7
[2] => 6
[3] => 3
[4] => 2
[5] => 1
)
StepIterator
以步长遍历可遍历的集合。
use Gielfeldt\Iterators\StepIterator; $input = new \ArrayIterator(range(1, 10)); $stepped = new StepIterator($input, 2); print_r(iterator_to_array($stepped));
输出
Array
(
[0] => 1
[2] => 3
[4] => 5
[6] => 7
[8] => 9
)
UniqueIterator
类似于array_unique()。也支持自定义回调函数。
use Gielfeldt\Iterators\UniqueIterator; $input = new \ArrayIterator([-4, -3, -2, -1, 0, 1, 2, 3, 5]); // Unique elements by their square. $iterator = new UniqueIterator($input, UniqueIterator::REINDEX, function ($iterator) { return $iterator->current() * $iterator->current(); }); print_r(iterator_to_array($iterator));
输出
Array
(
[0] => -4
[1] => -3
[2] => -2
[3] => -1
[4] => 0
[8] => 5
)
ValuesIterator
类似于array_values()。
use Gielfeldt\Iterators\ValuesIterator; $input = new \ArrayIterator([ 'key1' => 'value1', 'key2' => 'value2', 'key3' => 'value3', ]); $iterator = new ValuesIterator($input); print_r(iterator_to_array($iterator));
输出
Array
(
[0] => value1
[1] => value2
[2] => value3
)
不是迭代器...
这些都是SPL文件处理的扩展。
CsvFileObject
是SplFileObject在csv模式下的扩展,但支持csv头。
use Gielfeldt\Iterators\CsvFileObject; // Load csv file and dump it. $file = new CsvFileObject('somefile.csv'); print_r(iterator_to_array($file)); // Same but csv comes via a string variable. $csvdata = "Columm1,Column2\nValue1,Value2\nValue3,Value4"; $file = new CsvFileObject('data://application/octet,' . $csvdata); print_r(iterator_to_array($file));
输出
Array
(
[0] => Array
(
[Columm1] => Value1
[Column2] => Value2
)
[1] => Array
(
[Columm1] => Value3
[Column2] => Value4
)
)
Array
(
[0] => Array
(
[Columm1] => Value1
[Column2] => Value2
)
[1] => Array
(
[Columm1] => Value3
[Column2] => Value4
)
)
AtomicTempFileObject
AtomicTempFileObjects
辅助函数
包含各种辅助方法。
迭代器
use Gielfeldt\Iterators\Iterator; $input = new \ArrayIterator([1,2,3,4,5,6]); var_dump(Iterator::sum($input)); var_dump(Iterator::product($input)); var_dump(Iterator::average($input)); var_dump(Iterator::min($input)); var_dump(Iterator::max($input));
输出
int(21)
int(720)
double(3.5)
int(1)
int(6)
注意事项
- 可能有很多。