-
Notifications
You must be signed in to change notification settings - Fork 4
Expand file tree
/
Copy pathIterableObject.php
More file actions
143 lines (118 loc) · 3.54 KB
/
IterableObject.php
File metadata and controls
143 lines (118 loc) · 3.54 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
<?php
declare(strict_types=1);
namespace BenTools\IterableFunctions;
use AppendIterator;
use ArrayIterator;
use CallbackFilterIterator;
use Iterator;
use IteratorAggregate;
use IteratorIterator;
use Traversable;
use function array_chunk;
use function array_filter;
use function array_map;
use function iterator_to_array;
use const ARRAY_FILTER_USE_BOTH;
/**
* @internal
*
* @template TKey
* @template TValue
*
* @implements IteratorAggregate<TKey, TValue>
*/
final class IterableObject implements IteratorAggregate
{
/** @var iterable<TKey, TValue> */
private $iterable;
/** @var bool */
private $preserveKeys;
/** @param iterable<TKey, TValue> $iterable */
public function __construct(iterable $iterable, bool $preserveKeys = true)
{
$this->iterable = $iterable;
$this->preserveKeys = $preserveKeys;
}
/**
* @param (callable(TValue):bool)|(callable(TValue,TKey):bool)|null $filter
*
* @return self<TKey, TValue>
*/
public function filter(?callable $filter = null): self
{
if ($this->iterable instanceof Traversable) {
$filter ??=
/** @param mixed $value */
static function ($value): bool {
return (bool) $value;
};
return new self(new CallbackFilterIterator(new IteratorIterator($this->iterable), $filter));
}
$filtered = $filter === null
? array_filter($this->iterable)
: array_filter($this->iterable, $filter, ARRAY_FILTER_USE_BOTH);
return new self($filtered);
}
/**
* @param callable(TValue):TResult $mapper
*
* @return self<TKey, TResult>
*
* @template TResult
*/
public function map(callable $mapper): self
{
if ($this->iterable instanceof Traversable) {
return new self(new MappedTraversable($this->iterable, $mapper));
}
return new self(array_map($mapper, $this->iterable));
}
/**
* @param iterable<TKey, TValue> ...$args
*
* @return self<TKey, TValue>
*/
public function merge(iterable ...$args): self
{
if ($args === []) {
return $this;
}
$toIterator = static function (iterable $iterable): Iterator {
if ($iterable instanceof Traversable) {
return new IteratorIterator($iterable);
}
return new ArrayIterator($iterable);
};
$iterator = new AppendIterator();
$iterator->append($toIterator($this->iterable));
foreach ($args as $iterable) {
$iterator->append($toIterator($iterable));
}
return new self($iterator, false);
}
/**
* @return self<int, TValue>
*/
public function values(): self
{
return new self(new WithoutKeysTraversable($this->iterable));
}
/** @return iterable<int, iterable<TKey, TValue>> */
public function chunk(int $size): iterable
{
if ($this->iterable instanceof Traversable) {
return new ChunkIterator($this->iterable, $size, $this->preserveKeys);
}
return array_chunk($this->iterable, $size, $this->preserveKeys);
}
/** @return Traversable<TKey, TValue> */
public function getIterator(): Traversable
{
yield from $this->iterable;
}
/** @return array<array-key, TValue> */
public function asArray(): array
{
return $this->iterable instanceof Traversable ? iterator_to_array($this->iterable, $this->preserveKeys) : $this->iterable;
}
}