1
|
|
|
<?php |
2
|
|
|
/** |
3
|
|
|
* @copyright Zicht Online <http://zicht.nl> |
4
|
|
|
*/ |
5
|
|
|
|
6
|
|
|
namespace Zicht\Itertools; |
7
|
|
|
|
8
|
|
|
use Zicht\Itertools\lib\AccumulateIterator; |
9
|
|
|
use Zicht\Itertools\lib\ChainIterator; |
10
|
|
|
use Zicht\Itertools\lib\CountIterator; |
11
|
|
|
use Zicht\Itertools\lib\CycleIterator; |
12
|
|
|
use Zicht\Itertools\lib\FilterIterator; |
13
|
|
|
use Zicht\Itertools\lib\GroupbyIterator; |
14
|
|
|
use Zicht\Itertools\lib\Interfaces\AccumulateInterface; |
15
|
|
|
use Zicht\Itertools\lib\Interfaces\AllInterface; |
16
|
|
|
use Zicht\Itertools\lib\Interfaces\ChainInterface; |
17
|
|
|
use Zicht\Itertools\lib\Interfaces\CollapseInterface; |
18
|
|
|
use Zicht\Itertools\lib\Interfaces\CycleInterface; |
19
|
|
|
use Zicht\Itertools\lib\Interfaces\FilterInterface; |
20
|
|
|
use Zicht\Itertools\lib\Interfaces\FiniteIterableInterface; |
21
|
|
|
use Zicht\Itertools\lib\Interfaces\FirstInterface; |
22
|
|
|
use Zicht\Itertools\lib\Interfaces\GroupByInterface; |
23
|
|
|
use Zicht\Itertools\lib\Interfaces\LastInterface; |
24
|
|
|
use Zicht\Itertools\lib\Interfaces\MapByInterface; |
25
|
|
|
use Zicht\Itertools\lib\Interfaces\ReduceInterface; |
26
|
|
|
use Zicht\Itertools\lib\Interfaces\ReversedInterface; |
27
|
|
|
use Zicht\Itertools\lib\Interfaces\SliceInterface; |
28
|
|
|
use Zicht\Itertools\lib\Interfaces\SortedInterface; |
29
|
|
|
use Zicht\Itertools\lib\Interfaces\UniqueInterface; |
30
|
|
|
use Zicht\Itertools\lib\Interfaces\ZipInterface; |
31
|
|
|
use Zicht\Itertools\lib\IterableIterator; |
32
|
|
|
use Zicht\Itertools\lib\MapByIterator; |
33
|
|
|
use Zicht\Itertools\lib\MapIterator; |
34
|
|
|
use Zicht\Itertools\lib\RepeatIterator; |
35
|
|
|
use Zicht\Itertools\lib\ReversedIterator; |
36
|
|
|
use Zicht\Itertools\lib\SliceIterator; |
37
|
|
|
use Zicht\Itertools\lib\SortedIterator; |
38
|
|
|
use Zicht\Itertools\lib\UniqueIterator; |
39
|
|
|
use Zicht\Itertools\lib\ZipIterator; |
40
|
|
|
use Zicht\Itertools\reductions; |
41
|
|
|
use Zicht\Itertools\util\Conversions; |
42
|
|
|
|
43
|
|
|
/** |
44
|
|
|
* Transforms anything into an \Iterator or throws an \InvalidArgumentException |
45
|
|
|
* |
46
|
|
|
* @param array|string|\Iterator $iterable |
47
|
|
|
* @return \Iterator |
48
|
|
|
* @deprecated Use \Zicht\Itertools\util\Conversions::mixedToIterator, will be removed in version 3.0 |
49
|
|
|
*/ |
50
|
|
|
function mixedToIterator($iterable) // phpcs:ignore Zicht.NamingConventions.Functions.GlobalNaming |
51
|
|
|
{ |
52
|
|
|
return Conversions::mixedToIterator($iterable); |
53
|
|
|
} |
54
|
|
|
|
55
|
|
|
/** |
56
|
|
|
* Try to transforms something into a \Closure |
57
|
|
|
* |
58
|
|
|
* @param null|\Closure $closure |
59
|
|
|
* @return \Closure |
60
|
|
|
* @deprecated Use \Zicht\Itertools\util\Conversions::mixedToClosure, will be removed in version 3.0 |
61
|
|
|
*/ |
62
|
|
|
function mixedToClosure($closure) // phpcs:ignore Zicht.NamingConventions.Functions.GlobalNaming |
63
|
|
|
{ |
64
|
|
|
return Conversions::mixedToClosure($closure); |
65
|
|
|
} |
66
|
|
|
|
67
|
|
|
/** |
68
|
|
|
* Try to transforms something into a \Closure that gets a value from $strategy |
69
|
|
|
* |
70
|
|
|
* @param null|string|\Closure $strategy |
71
|
|
|
* @return \Closure |
72
|
|
|
* @deprecated Use \Zicht\Itertools\util\Conversions::mixedToValueGetter, will be removed in version 3.0 |
73
|
|
|
*/ |
74
|
|
|
function mixedToValueGetter($strategy) // phpcs:ignore Zicht.NamingConventions.Functions.GlobalNaming |
75
|
|
|
{ |
76
|
|
|
return Conversions::mixedToValueGetter($strategy); |
77
|
|
|
} |
78
|
|
|
|
79
|
|
|
/** |
80
|
|
|
* Try to transform something into a \Closure |
81
|
|
|
* |
82
|
|
|
* @param string|\Closure $closure |
83
|
|
|
* @return \Closure |
84
|
|
|
* @deprecated Will be removed in version 3.0, no replacement will be needed |
85
|
|
|
*/ |
86
|
|
|
function mixedToOperationClosure($closure) // phpcs:ignore Zicht.NamingConventions.Functions.GlobalNaming |
87
|
|
|
{ |
88
|
|
|
if (is_string($closure)) { |
89
|
|
|
$closure = reductions\get_reduction($closure, $closure); |
|
|
|
|
90
|
|
|
} |
91
|
|
|
|
92
|
|
|
if (!($closure instanceof \Closure)) { |
93
|
|
|
throw new \InvalidArgumentException('Argument $closure must be a \Closure or string (i.e. "add", "join", etc)'); |
94
|
|
|
} |
95
|
|
|
|
96
|
|
|
return $closure; |
97
|
|
|
} |
98
|
|
|
|
99
|
|
|
/** |
100
|
|
|
* Make an iterator that returns accumulated sums |
101
|
|
|
* |
102
|
|
|
* If the optional $closure argument is supplied, it should be a string: |
103
|
|
|
* add, sub, mul, min, or max. Or it can be a \Closure taking two |
104
|
|
|
* arguments that will be used to instead of addition. |
105
|
|
|
* |
106
|
|
|
* > accumulate([1,2,3,4,5]) |
107
|
|
|
* 1 3 6 10 15 |
108
|
|
|
* |
109
|
|
|
* > accumulate(['One', 'Two', 'Three'], function ($a, $b) { return $a . $b; }) |
110
|
|
|
* 'One' 'OneTwo' 'OneTwoThree' |
111
|
|
|
* |
112
|
|
|
* @param array|string|\Iterator $iterable |
113
|
|
|
* @param string|\Closure $closure |
114
|
|
|
* @return AccumulateIterator |
115
|
|
|
* @deprecated Use iterable($iterable)->accumulate($closure), will be removed in version 3.0 |
116
|
|
|
*/ |
117
|
|
|
function accumulate($iterable, $closure = 'add') |
118
|
|
|
{ |
119
|
|
|
if (!($iterable instanceof AccumulateInterface)) { |
120
|
|
|
$iterable = iterable($iterable); |
121
|
|
|
} |
122
|
|
|
|
123
|
|
|
return $iterable->accumulate($closure); |
124
|
|
|
} |
125
|
|
|
|
126
|
|
|
/** |
127
|
|
|
* Reduce an iterator to a single value |
128
|
|
|
* |
129
|
|
|
* > reduce([1,2,3]) |
130
|
|
|
* 6 |
131
|
|
|
* |
132
|
|
|
* > reduce([1,2,3], 'max') |
133
|
|
|
* 3 |
134
|
|
|
* |
135
|
|
|
* > reduce([1,2,3], 'sub', 10) |
136
|
|
|
* 4 |
137
|
|
|
* |
138
|
|
|
* > reduce([], 'min', 1) |
139
|
|
|
* 1 |
140
|
|
|
* |
141
|
|
|
* @param array|string|\Iterator $iterable |
142
|
|
|
* @param string|\Closure $closure |
143
|
|
|
* @param mixed $initializer |
144
|
|
|
* @return mixed |
145
|
|
|
* @deprecated Use iterable($iterable)->reduce($closure, $initializer), will be removed in version 3.0 |
146
|
|
|
*/ |
147
|
|
|
function reduce($iterable, $closure = 'add', $initializer = null) |
148
|
|
|
{ |
149
|
|
|
if (!($iterable instanceof ReduceInterface)) { |
150
|
|
|
$iterable = iterable($iterable); |
151
|
|
|
} |
152
|
|
|
|
153
|
|
|
return $iterable->reduce($closure, $initializer); |
154
|
|
|
} |
155
|
|
|
|
156
|
|
|
/** |
157
|
|
|
* Collapse a two dimentional iterator into a one dimentional iterator |
158
|
|
|
* |
159
|
|
|
* > collapse([1, 2], [3, 4]) |
160
|
|
|
* 1, 2, 3, 4 |
161
|
|
|
* |
162
|
|
|
* @param array|string|\Iterator $iterable |
163
|
|
|
* @return lib\CollapseIterator |
164
|
|
|
* @deprecated Use iterable($iterable)->collapse(), will be removed in version 3.0 |
165
|
|
|
*/ |
166
|
|
|
function collapse($iterable) |
167
|
|
|
{ |
168
|
|
|
if (!($iterable instanceof CollapseInterface)) { |
169
|
|
|
$iterable = iterable($iterable); |
170
|
|
|
} |
171
|
|
|
|
172
|
|
|
return $iterable->collapse(); |
173
|
|
|
} |
174
|
|
|
|
175
|
|
|
/** |
176
|
|
|
* Make an iterator that contains all consecutive elements from all provided iterables. |
177
|
|
|
* |
178
|
|
|
* The resulting iterator contains elements from the first iterable in the parameters |
179
|
|
|
* until it is exhausted, then proceeds to the next iterable in the parameters, until |
180
|
|
|
* all the iterables are exhausted. Used for creating consecutive |
181
|
|
|
* sequences as a single sequence |
182
|
|
|
* |
183
|
|
|
* > chain([1, 2, 3], [4, 5, 6]) |
184
|
|
|
* 1 2 3 4 5 6 |
185
|
|
|
* |
186
|
|
|
* > chain('ABC', 'DEF') |
187
|
|
|
* A B C D E F |
188
|
|
|
* |
189
|
|
|
* @return ChainIterator |
190
|
|
|
* @deprecated Use iterable($iterable)->chain($iterable, ...), will be removed in version 3.0 |
191
|
|
|
*/ |
192
|
|
|
function chain() |
193
|
|
|
{ |
194
|
|
|
// note, once we stop supporting php 5.5, we can rewrite the code below |
195
|
|
|
// to the chain(...$iterables) structure. |
196
|
|
|
// http://php.net/manual/en/functions.arguments.php#functions.variable-arg-list |
197
|
|
|
|
198
|
|
|
$args = func_get_args(); |
199
|
|
|
if (sizeof($args) > 0) { |
200
|
|
|
list($iterable) = array_slice($args, 0, 1); |
201
|
|
|
$iterables = array_slice($args, 1); |
202
|
|
|
} else { |
203
|
|
|
$iterable = null; |
204
|
|
|
$iterables = []; |
205
|
|
|
} |
206
|
|
|
|
207
|
|
|
if (!($iterable instanceof ChainInterface)) { |
208
|
|
|
$iterable = iterable($iterable); |
209
|
|
|
} |
210
|
|
|
|
211
|
|
|
return call_user_func_array([$iterable, 'chain'], $iterables); |
212
|
|
|
} |
213
|
|
|
|
214
|
|
|
/** |
215
|
|
|
* Make an iterator that returns evenly spaced values starting with |
216
|
|
|
* number $start |
217
|
|
|
* |
218
|
|
|
* > count(10) |
219
|
|
|
* 10 11 12 13 14 ... |
220
|
|
|
* |
221
|
|
|
* > count(2.5, 0.5) |
222
|
|
|
* 2.5 3.0 3.5 4.0 ... |
223
|
|
|
* |
224
|
|
|
* @param int|float $start |
225
|
|
|
* @param int|float $step |
226
|
|
|
* @return CountIterator |
227
|
|
|
* @deprecated Use new CountIterator($start, $step), will be removed in version 3.0 |
228
|
|
|
*/ |
229
|
|
|
function count($start = 0, $step = 1) |
230
|
|
|
{ |
231
|
|
|
if (!(is_int($start) || is_float($start))) { |
232
|
|
|
throw new \InvalidArgumentException('Argument $start must be an integer or float'); |
233
|
|
|
} |
234
|
|
|
|
235
|
|
|
if (!(is_int($step) || is_float($step))) { |
236
|
|
|
throw new \InvalidArgumentException('Argument $step must be an integer or float'); |
237
|
|
|
} |
238
|
|
|
|
239
|
|
|
return new CountIterator($start, $step); |
240
|
|
|
} |
241
|
|
|
|
242
|
|
|
/** |
243
|
|
|
* Make an iterator returning elements from the $iterable and saving a |
244
|
|
|
* copy of each. When the iterable is exhausted, return elements from |
245
|
|
|
* the saved copy, repeating indefinitely |
246
|
|
|
* |
247
|
|
|
* > cycle('ABCD') |
248
|
|
|
* A B C D A B C D A B C D ... |
249
|
|
|
* |
250
|
|
|
* @param array|string|\Iterator $iterable |
251
|
|
|
* @return CycleIterator |
252
|
|
|
* @deprecated Use iterable($iterable)->cycle(), will be removed in version 3.0 |
253
|
|
|
*/ |
254
|
|
|
function cycle($iterable) |
255
|
|
|
{ |
256
|
|
|
if (!($iterable instanceof CycleInterface)) { |
257
|
|
|
$iterable = iterable($iterable); |
258
|
|
|
} |
259
|
|
|
|
260
|
|
|
return $iterable->cycle(); |
261
|
|
|
} |
262
|
|
|
|
263
|
|
|
/** |
264
|
|
|
* Make an iterator returning values from $iterable and keys from |
265
|
|
|
* $strategy |
266
|
|
|
* |
267
|
|
|
* When $strategy is a string, the key is obtained through one of |
268
|
|
|
* the following: |
269
|
|
|
* 1. $value->{$strategy}, when $value is an object and |
270
|
|
|
* $strategy is an existing property, |
271
|
|
|
* 2. call $value->{$strategy}(), when $value is an object and |
272
|
|
|
* $strategy is an existing method, |
273
|
|
|
* 3. $value[$strategy], when $value is an array and $strategy |
274
|
|
|
* is an existing key, |
275
|
|
|
* 4. otherwise the key will default to null. |
276
|
|
|
* |
277
|
|
|
* Alternatively $strategy can be a closure. In this case the |
278
|
|
|
* $strategy closure is called with each value in $iterable and the |
279
|
|
|
* key will be its return value. |
280
|
|
|
* |
281
|
|
|
* > $list = [['id'=>1, 'title'=>'one'], ['id'=>2, 'title'=>'two']] |
282
|
|
|
* > mapBy('id', $list) |
283
|
|
|
* 1=>['id'=>1, 'title'=>'one'] 2=>['id'=>2, 'title'=>'two'] |
284
|
|
|
* |
285
|
|
|
* @param null|string|\Closure $strategy |
286
|
|
|
* @param array|string|\Iterator $iterable |
287
|
|
|
* @return MapByIterator |
288
|
|
|
* @deprecated Use iterable($iterable)->mapBy($strategy), will be removed in version 3.0 |
289
|
|
|
*/ |
290
|
|
|
function map_by($strategy, $iterable) |
291
|
|
|
{ |
292
|
|
|
// In version 3.0 mapBy and map_by will be removed |
293
|
|
|
// as its functionality will be merged into map. |
294
|
|
|
|
295
|
|
|
if (!($iterable instanceof MapByInterface)) { |
296
|
|
|
$iterable = iterable($iterable); |
297
|
|
|
} |
298
|
|
|
|
299
|
|
|
return $iterable->mapBy($strategy); |
300
|
|
|
} |
301
|
|
|
|
302
|
|
|
/** |
303
|
|
|
* Make an iterator returning values from $iterable and keys from |
304
|
|
|
* $strategy |
305
|
|
|
* |
306
|
|
|
* @param null|string|\Closure $strategy |
307
|
|
|
* @param array|string|\Iterator $iterable |
308
|
|
|
* @return MapByIterator |
309
|
|
|
* @deprecated Please use map_by, will be removed in version 3.0 |
310
|
|
|
* @deprecated Use iterable($iterable)->mapBy($strategy), will be removed in version 3.0 |
311
|
|
|
*/ |
312
|
|
|
function mapBy($strategy, $iterable) // phpcs:ignore Zicht.NamingConventions.Functions.GlobalNaming |
313
|
|
|
{ |
314
|
|
|
if (!($iterable instanceof MapByInterface)) { |
315
|
|
|
$iterable = iterable($iterable); |
316
|
|
|
} |
317
|
|
|
|
318
|
|
|
return $iterable->mapBy($strategy); |
319
|
|
|
} |
320
|
|
|
|
321
|
|
|
/** |
322
|
|
|
* Make an iterator returning values from $iterable and keys from |
323
|
|
|
* $strategy |
324
|
|
|
* |
325
|
|
|
* @param null|string|\Closure $strategy |
326
|
|
|
* @param array|string|\Iterator $iterable |
327
|
|
|
* @return MapByIterator |
328
|
|
|
* @deprecated Use iterable($iterable)->mapBy($strategy), will be removed in version 3.0 |
329
|
|
|
*/ |
330
|
|
|
function keyCallback($strategy, $iterable) // phpcs:ignore Zicht.NamingConventions.Functions.GlobalNaming |
331
|
|
|
{ |
332
|
|
|
return map_by($strategy, $iterable); |
333
|
|
|
} |
334
|
|
|
|
335
|
|
|
/** |
336
|
|
|
* Make an iterator that applies $strategy to every entry in the iterables |
337
|
|
|
* |
338
|
|
|
* If one iterable is passed, $strategy is called for each entry in |
339
|
|
|
* the $iterable, where the first argument is the value and the |
340
|
|
|
* second argument is the key of the entry |
341
|
|
|
* |
342
|
|
|
* If more than one iterable is passed, $strategy is called with the |
343
|
|
|
* values and the keys from the iterables. For example, the first |
344
|
|
|
* call to $strategy will be: |
345
|
|
|
* $strategy($value_iterable1, $value_iterable2, $key_iterable2, $key_iterable2) |
346
|
|
|
* |
347
|
|
|
* With multiple iterables, the iterator stops when the shortest |
348
|
|
|
* iterable is exhausted. |
349
|
|
|
* |
350
|
|
|
* > $minimal = function ($value) { return min(3, $value); }; |
351
|
|
|
* > map($minimal, [1, 2, 3, 4]); |
352
|
|
|
* 3 3 3 4 |
353
|
|
|
* |
354
|
|
|
* > $average = function ($value1, $value2) { return ($value1 + $value2) / 2; }; |
355
|
|
|
* > map($average, [1, 2, 3], [4, 5, 6]); |
356
|
|
|
* 2.5 3.5 4.5 |
357
|
|
|
* |
358
|
|
|
* @param null|string|\Closure $strategy |
359
|
|
|
* @param array|string|\Iterator $iterable Additional $iterable parameters may follow |
360
|
|
|
* @return MapIterator |
361
|
|
|
* @deprecated Use iterable($iterable)->map($strategy, [$iterable2, ...]), will be removed in version 3.0 |
362
|
|
|
*/ |
363
|
|
View Code Duplication |
function map($strategy, $iterable) |
|
|
|
|
364
|
|
|
{ |
365
|
|
|
// note, once we stop supporting php 5.5, we can rewrite the code below |
366
|
|
|
// to the map(...$iterables) structure. |
367
|
|
|
// http://php.net/manual/en/functions.arguments.php#functions.variable-arg-list |
368
|
|
|
|
369
|
|
|
if (func_num_args() > 2) { |
370
|
|
|
$iterables = array_slice(func_get_args(), 2); |
371
|
|
|
} else { |
372
|
|
|
$iterables = []; |
373
|
|
|
} |
374
|
|
|
|
375
|
|
|
if (!($iterable instanceof ChainInterface)) { |
376
|
|
|
$iterable = iterable($iterable); |
377
|
|
|
} |
378
|
|
|
|
379
|
|
|
return call_user_func_array([$iterable, 'map'], array_merge([$strategy], $iterables)); |
380
|
|
|
} |
381
|
|
|
|
382
|
|
|
/** |
383
|
|
|
* Select values from the iterator by applying a function to each of the iterator values, i.e., mapping it to the |
384
|
|
|
* value with a strategy based on the input, similar to map_key |
385
|
|
|
* |
386
|
|
|
* @param null|string|\Closure $strategy |
387
|
|
|
* @param array|string|\Iterator $iterable |
388
|
|
|
* @param bool $flatten |
389
|
|
|
* @return array|MapIterator |
390
|
|
|
* @deprecated Use map(...)->values() instead (when flatten true), will be removed in version 3.0 |
391
|
|
|
*/ |
392
|
|
|
function select($strategy, $iterable, $flatten = true) |
393
|
|
|
{ |
394
|
|
|
if (!is_bool($flatten)) { |
395
|
|
|
throw new \InvalidArgumentException('Argument $FLATTEN must be a boolean'); |
396
|
|
|
} |
397
|
|
|
|
398
|
|
|
$ret = new MapIterator( |
399
|
|
|
Conversions::mixedToValueGetter($strategy), |
400
|
|
|
Conversions::mixedToIterator($iterable) |
401
|
|
|
); |
402
|
|
|
if ($flatten) { |
403
|
|
|
return $ret->values(); |
404
|
|
|
} |
405
|
|
|
return $ret; |
406
|
|
|
} |
407
|
|
|
|
408
|
|
|
/** |
409
|
|
|
* Make an iterator that returns $mixed over and over again. Runs |
410
|
|
|
* indefinitely unless the $times argument is specified |
411
|
|
|
* |
412
|
|
|
* > repeat(2) |
413
|
|
|
* 2 2 2 2 2 ... |
414
|
|
|
* |
415
|
|
|
* > repeat(10, 3) |
416
|
|
|
* 10 10 10 |
417
|
|
|
* |
418
|
|
|
* @param mixed $mixed |
419
|
|
|
* @param null|int $times |
420
|
|
|
* @return RepeatIterator |
421
|
|
|
* @deprecated Use new RepeatIterator(mixed, $times), will be removed in version 3.0 |
422
|
|
|
*/ |
423
|
|
|
function repeat($mixed, $times = null) |
424
|
|
|
{ |
425
|
|
|
if (!(is_null($times) || (is_int($times) && $times >= 0))) { |
426
|
|
|
throw new \InvalidArgumentException('Argument $times must be null or a positive integer'); |
427
|
|
|
} |
428
|
|
|
|
429
|
|
|
return new RepeatIterator($mixed, $times); |
430
|
|
|
} |
431
|
|
|
|
432
|
|
|
/** |
433
|
|
|
* Make an iterator that returns consecutive groups from the |
434
|
|
|
* $iterable. Generally, the $iterable needs to already be sorted on |
435
|
|
|
* the same key function |
436
|
|
|
* |
437
|
|
|
* When $strategy is a string, the key is obtained through one of |
438
|
|
|
* the following: |
439
|
|
|
* 1. $value->{$strategy}, when $value is an object and |
440
|
|
|
* $strategy is an existing property, |
441
|
|
|
* 2. call $value->{$strategy}(), when $value is an object and |
442
|
|
|
* $strategy is an existing method, |
443
|
|
|
* 3. $value[$strategy], when $value is an array and $strategy |
444
|
|
|
* is an existing key, |
445
|
|
|
* 4. otherwise the key will default to null. |
446
|
|
|
* |
447
|
|
|
* Alternatively $strategy can be a closure. In this case the |
448
|
|
|
* $strategy closure is called with each value in $iterable and the |
449
|
|
|
* key will be its return value. $strategy is called with two |
450
|
|
|
* parameters: the value and the key of the iterable as the first and |
451
|
|
|
* second parameter, respectively. |
452
|
|
|
* |
453
|
|
|
* The operation of groupBy() is similar to the uniq filter in Unix. |
454
|
|
|
* It generates a break or new group every time the value of the key |
455
|
|
|
* function changes (which is why it is usually necessary to have |
456
|
|
|
* sorted the data using the same key function). That behavior |
457
|
|
|
* differs from SQL's GROUP BY which aggregates common elements |
458
|
|
|
* regardless of their input order. |
459
|
|
|
* |
460
|
|
|
* > $list = [['type'=>'A', 'title'=>'one'], ['type'=>'A', 'title'=>'two'], ['type'=>'B', 'title'=>'three']] |
461
|
|
|
* > groupby('type', $list) |
462
|
|
|
* 'A'=>[['type'=>'A', 'title'=>'one'], ['type'=>'A', 'title'=>'two']] 'B'=>[['type'=>'B', 'title'=>'three']] |
463
|
|
|
* |
464
|
|
|
* @param null|string|\Closure $strategy |
465
|
|
|
* @param array|string|\Iterator $iterable |
466
|
|
|
* @param boolean $sort |
467
|
|
|
* @return GroupbyIterator |
468
|
|
|
* @deprecated Use iterable($iterable)->groupBy($strategy, $sort), will be removed in version 3.0 |
469
|
|
|
*/ |
470
|
|
|
function group_by($strategy, $iterable, $sort = true) |
471
|
|
|
{ |
472
|
|
|
if (!($iterable instanceof GroupByInterface)) { |
473
|
|
|
$iterable = iterable($iterable); |
474
|
|
|
} |
475
|
|
|
|
476
|
|
|
return $iterable->groupBy($strategy, $sort); |
477
|
|
|
} |
478
|
|
|
|
479
|
|
|
/** |
480
|
|
|
* Make an iterator that returns consecutive groups from the |
481
|
|
|
* $iterable. Generally, the $iterable needs to already be sorted on |
482
|
|
|
* the same key function |
483
|
|
|
* |
484
|
|
|
* @param null|string|\Closure $strategy |
485
|
|
|
* @param array|string|\Iterator $iterable |
486
|
|
|
* @param boolean $sort |
487
|
|
|
* @return GroupbyIterator |
488
|
|
|
* @deprecated Use iterable($iterable)->groupBy($strategy, $sort), will be removed in version 3.0 |
489
|
|
|
*/ |
490
|
|
|
function groupBy($strategy, $iterable, $sort = true) // phpcs:ignore Zicht.NamingConventions.Functions.GlobalNaming |
491
|
|
|
{ |
492
|
|
|
if (!($iterable instanceof GroupByInterface)) { |
493
|
|
|
$iterable = iterable($iterable); |
494
|
|
|
} |
495
|
|
|
|
496
|
|
|
return $iterable->groupBy($strategy, $sort); |
497
|
|
|
} |
498
|
|
|
|
499
|
|
|
/** |
500
|
|
|
* Make an iterator that returns the values from $iterable sorted by |
501
|
|
|
* $strategy |
502
|
|
|
* |
503
|
|
|
* When determining the order of two entries the $strategy is called |
504
|
|
|
* twice, once for each value, and the results are used to determine |
505
|
|
|
* the order. $strategy is called with two parameters: the value and |
506
|
|
|
* the key of the iterable as the first and second parameter, respectively. |
507
|
|
|
* |
508
|
|
|
* When $reverse is true the order of the results are reversed. |
509
|
|
|
* |
510
|
|
|
* The sorted() function is guaranteed to be stable. A sort is stable |
511
|
|
|
* if it guarantees not to change the relative order of elements that |
512
|
|
|
* compare equal. this is helpful for sorting in multiple passes (for |
513
|
|
|
* example, sort by department, then by salary grade). This also |
514
|
|
|
* holds up when $reverse is true. |
515
|
|
|
* |
516
|
|
|
* > $list = [['type'=>'B', 'title'=>'second'], ['type'=>'C', 'title'=>'third'], ['type'=>'A', 'title'=>'first']] |
517
|
|
|
* > sorted('type', $list) |
518
|
|
|
* ['type'=>'A', 'title'=>'first'] ['type'=>'B', 'title'=>'second']] ['type'=>'C', 'title'=>'third'] |
519
|
|
|
* |
520
|
|
|
* @param null|string|\Closure $strategy |
521
|
|
|
* @param array|string|\Iterator $iterable |
522
|
|
|
* @param boolean $reverse |
523
|
|
|
* @return SortedIterator |
524
|
|
|
* @deprecated Use iterable($iterable)->sorted($strategy, $reverse), will be removed in version 3.0 |
525
|
|
|
*/ |
526
|
|
|
function sorted($strategy, $iterable, $reverse = false) |
527
|
|
|
{ |
528
|
|
|
if (!($iterable instanceof SortedInterface)) { |
529
|
|
|
$iterable = iterable($iterable); |
530
|
|
|
} |
531
|
|
|
|
532
|
|
|
return $iterable->sorted($strategy, $reverse); |
533
|
|
|
} |
534
|
|
|
|
535
|
|
|
/** |
536
|
|
|
* Make an iterator that returns values from $iterable where the |
537
|
|
|
* $strategy determines that the values are not empty |
538
|
|
|
* |
539
|
|
|
* An optional $strategy may be given, this must be either null, |
540
|
|
|
* a string, or a \Closure. |
541
|
|
|
* |
542
|
|
|
* Following the (optional) $strategy, one or more $iterable instances |
543
|
|
|
* must be given. They must be either an array, a string, or an \Iterator. |
544
|
|
|
* |
545
|
|
|
* @return FilterIterator |
546
|
|
|
* @deprecated Use iterable($iterable)->filter($strategy), will be removed in version 3.0 |
547
|
|
|
*/ |
548
|
|
View Code Duplication |
function filter() |
|
|
|
|
549
|
|
|
{ |
550
|
|
|
// note, once we stop supporting php 5.5, we can rewrite the code below |
551
|
|
|
// to the filter(...$iterables) structure. |
552
|
|
|
// http://php.net/manual/en/functions.arguments.php#functions.variable-arg-list |
553
|
|
|
|
554
|
|
|
$args = func_get_args(); |
555
|
|
|
switch (sizeof($args)) { |
556
|
|
|
case 1: |
557
|
|
|
$strategy = null; |
558
|
|
|
$iterable = $args[0]; |
559
|
|
|
break; |
560
|
|
|
|
561
|
|
|
case 2: |
562
|
|
|
$strategy = $args[0]; |
563
|
|
|
$iterable = $args[1]; |
564
|
|
|
break; |
565
|
|
|
|
566
|
|
|
default: |
567
|
|
|
throw new \InvalidArgumentException('filter requires either one (iterable) or two (strategy, iterable) arguments'); |
568
|
|
|
} |
569
|
|
|
|
570
|
|
|
if (!($iterable instanceof FilterInterface)) { |
571
|
|
|
$iterable = iterable($iterable); |
572
|
|
|
} |
573
|
|
|
|
574
|
|
|
return $iterable->filter($strategy); |
575
|
|
|
} |
576
|
|
|
|
577
|
|
|
/** |
578
|
|
|
* Make an iterator that returns values from $iterable where the |
579
|
|
|
* $strategy determines that the values are not empty |
580
|
|
|
* |
581
|
|
|
* An $strategy must be given, this must be either null, a string, |
582
|
|
|
* or a \Closure. |
583
|
|
|
* |
584
|
|
|
* Following the $strategy, an optional $closure may be given, this |
585
|
|
|
* closure is called to determine is the value (which results from |
586
|
|
|
* $strategy) is or is not filtered. Note that without providing a |
587
|
|
|
* $closure, the function !empty(...) is used instead. |
588
|
|
|
* |
589
|
|
|
* Following the (optional) $closure, one or more $iterable instances |
590
|
|
|
* must be given. They must be either an array, a string, or an \Iterator. |
591
|
|
|
* |
592
|
|
|
* @return FilterIterator |
593
|
|
|
* @deprecated Use iterable($iterable)->filter($strategy), will be removed in version 3.0 |
594
|
|
|
*/ |
595
|
|
|
function filterBy() // phpcs:ignore Zicht.NamingConventions.Functions.GlobalNaming |
596
|
|
|
{ |
597
|
|
|
// note, once we stop supporting php 5.5, we can rewrite the code below |
598
|
|
|
// to the filterBy(...$iterables) structure. |
599
|
|
|
// http://php.net/manual/en/functions.arguments.php#functions.variable-arg-list |
600
|
|
|
|
601
|
|
|
$args = func_get_args(); |
602
|
|
|
switch (sizeof($args)) { |
603
|
|
View Code Duplication |
case 2: |
|
|
|
|
604
|
|
|
$strategy = Conversions::mixedToValueGetter($args[0]); |
605
|
|
|
$closure = function ($value, $key) use ($strategy) { |
606
|
|
|
$tempVarPhp54 = call_user_func($strategy, $value, $key); |
607
|
|
|
return !empty($tempVarPhp54); |
608
|
|
|
}; |
609
|
|
|
$iterable = Conversions::mixedToIterator($args[1]); |
610
|
|
|
break; |
611
|
|
|
|
612
|
|
View Code Duplication |
case 3: |
|
|
|
|
613
|
|
|
$strategy = Conversions::mixedToValueGetter($args[0]); |
614
|
|
|
$userClosure = $args[1]; |
615
|
|
|
$closure = function ($value, $key) use ($strategy, $userClosure) { |
616
|
|
|
return call_user_func($userClosure, call_user_func($strategy, $value, $key)); |
617
|
|
|
}; |
618
|
|
|
$iterable = Conversions::mixedToIterator($args[2]); |
619
|
|
|
break; |
620
|
|
|
|
621
|
|
|
default: |
622
|
|
|
throw new \InvalidArgumentException('filterBy requires either two (strategy, iterable) or three (strategy, closure, iterable) arguments'); |
623
|
|
|
} |
624
|
|
|
|
625
|
|
|
return new FilterIterator($closure, $iterable); |
626
|
|
|
} |
627
|
|
|
|
628
|
|
|
/** |
629
|
|
|
* Returns an iterator where one or more iterables are zipped together |
630
|
|
|
* |
631
|
|
|
* This function returns a list of tuples, where the i-th tuple contains |
632
|
|
|
* the i-th element from each of the argument sequences or iterables. |
633
|
|
|
* |
634
|
|
|
* The returned list is truncated in length to the length of the |
635
|
|
|
* shortest argument sequence. |
636
|
|
|
* |
637
|
|
|
* > zip([1, 2, 3], ['a', 'b', 'c']) |
638
|
|
|
* [1, 'a'] [2, 'b'] [3, 'c'] |
639
|
|
|
* |
640
|
|
|
* @param array|string|\Iterator $iterable Additional $iterable parameters may follow |
641
|
|
|
* @return ZipIterator |
642
|
|
|
* @deprecated Use iterable($iterable)->zip($iterable2, [$iterable3, ...]), will be removed in version 3.0 |
643
|
|
|
*/ |
644
|
|
View Code Duplication |
function zip($iterable) |
|
|
|
|
645
|
|
|
{ |
646
|
|
|
// note, once we stop supporting php 5.5, we can rewrite the code below |
647
|
|
|
// to the zip(...$iterables) structure. |
648
|
|
|
// http://php.net/manual/en/functions.arguments.php#functions.variable-arg-list |
649
|
|
|
|
650
|
|
|
if (func_num_args() > 1) { |
651
|
|
|
$iterables = array_slice(func_get_args(), 1); |
652
|
|
|
} else { |
653
|
|
|
$iterables = []; |
654
|
|
|
} |
655
|
|
|
|
656
|
|
|
if (!($iterable instanceof ZipInterface)) { |
657
|
|
|
$iterable = iterable($iterable); |
658
|
|
|
} |
659
|
|
|
|
660
|
|
|
return call_user_func_array([$iterable, 'zip'], $iterables); |
661
|
|
|
} |
662
|
|
|
|
663
|
|
|
/** |
664
|
|
|
* Returns an iterable with all the elements from $iterable reversed |
665
|
|
|
* |
666
|
|
|
* @param array|string|\Iterator $iterable |
667
|
|
|
* @return ReversedIterator |
668
|
|
|
* @deprecated Use iterable($iterable)->reversed(), will be removed in version 3.0 |
669
|
|
|
*/ |
670
|
|
|
function reversed($iterable) |
671
|
|
|
{ |
672
|
|
|
if (!($iterable instanceof ReversedInterface)) { |
673
|
|
|
$iterable = iterable($iterable); |
674
|
|
|
} |
675
|
|
|
|
676
|
|
|
return $iterable->reversed(); |
677
|
|
|
} |
678
|
|
|
|
679
|
|
|
/** |
680
|
|
|
* Returns an iterator where the values from $strategy are unique |
681
|
|
|
* |
682
|
|
|
* An optional $strategy may be given to specify the value which is used |
683
|
|
|
* to determine whether the element is unique. When no $strategy is |
684
|
|
|
* given, the identity function is used, i.e. the value of the element |
685
|
|
|
* itself is used to determine whether the element is unique. |
686
|
|
|
* |
687
|
|
|
* Following the optional $strategy, a $iterable must be given. Otherwise, |
688
|
|
|
* an \InvalidArgumentException will be raised. |
689
|
|
|
* |
690
|
|
|
* > unique([1, 1, 2, 2, 3, 3]) |
691
|
|
|
* 1 2 3 |
692
|
|
|
* |
693
|
|
|
* > unique('id', [['id' => 1, 'value' => 'a'], ['id' => 1, 'value' => 'b']]) |
694
|
|
|
* ['id' => 1, 'value' => 'a'] # one element in this list |
695
|
|
|
* |
696
|
|
|
* @return UniqueIterator |
697
|
|
|
* @deprecated Use iterable($iterable)->unique($strategy), will be removed in version 3.0 |
698
|
|
|
*/ |
699
|
|
View Code Duplication |
function unique() |
|
|
|
|
700
|
|
|
{ |
701
|
|
|
$args = func_get_args(); |
702
|
|
|
switch (sizeof($args)) { |
703
|
|
|
case 1: |
704
|
|
|
$strategy = null; |
705
|
|
|
$iterable = $args[0]; |
706
|
|
|
break; |
707
|
|
|
|
708
|
|
|
case 2: |
709
|
|
|
$strategy = $args[0]; |
710
|
|
|
$iterable = $args[1]; |
711
|
|
|
break; |
712
|
|
|
|
713
|
|
|
default: |
714
|
|
|
throw new \InvalidArgumentException('unique requires either one (iterable) or two (strategy, iterable) arguments'); |
715
|
|
|
} |
716
|
|
|
|
717
|
|
|
if (!($iterable instanceof UniqueInterface)) { |
718
|
|
|
$iterable = iterable($iterable); |
719
|
|
|
} |
720
|
|
|
|
721
|
|
|
return $iterable->unique($strategy); |
722
|
|
|
} |
723
|
|
|
|
724
|
|
|
/** |
725
|
|
|
* Returns an iterator where the values from $strategy are unique |
726
|
|
|
* |
727
|
|
|
* @param null|string|\Closure $strategy |
728
|
|
|
* @param array|string|\Iterator $iterable |
729
|
|
|
* @return UniqueIterator |
730
|
|
|
* @deprecated Use iterable($iterable)->unique($strategy), will be removed in version 3.0 |
731
|
|
|
*/ |
732
|
|
View Code Duplication |
function uniqueBy($strategy, $iterable) // phpcs:ignore Zicht.NamingConventions.Functions.GlobalNaming |
|
|
|
|
733
|
|
|
{ |
734
|
|
|
$args = func_get_args(); |
735
|
|
|
switch (sizeof($args)) { |
736
|
|
|
case 1: |
737
|
|
|
$strategy = null; |
738
|
|
|
$iterable = $args[0]; |
739
|
|
|
break; |
740
|
|
|
|
741
|
|
|
case 2: |
742
|
|
|
$strategy = $args[0]; |
743
|
|
|
$iterable = $args[1]; |
744
|
|
|
break; |
745
|
|
|
|
746
|
|
|
default: |
747
|
|
|
throw new \InvalidArgumentException('unique requires either one (iterable) or two (strategy, iterable) arguments'); |
748
|
|
|
} |
749
|
|
|
|
750
|
|
|
if (!($iterable instanceof UniqueInterface)) { |
751
|
|
|
$iterable = iterable($iterable); |
752
|
|
|
} |
753
|
|
|
|
754
|
|
|
return $iterable->unique($strategy); |
755
|
|
|
} |
756
|
|
|
|
757
|
|
|
/** |
758
|
|
|
* Returns true when one or more element of $iterable is not empty, otherwise returns false |
759
|
|
|
* |
760
|
|
|
* An optional $strategy may be given to specify the value which is used |
761
|
|
|
* to determine weather the element evaluates to true. When no $strategy is |
762
|
|
|
* given, the identity function is used, i.e. the value of the element |
763
|
|
|
* itself is used to determine weather the element evaluates to true. |
764
|
|
|
* |
765
|
|
|
* Following the optional $strategy, an $iterable may be given. Its type may |
766
|
|
|
* be either array, string, or \Iterator. When no $iterable is given, false |
767
|
|
|
* is returned. |
768
|
|
|
* |
769
|
|
|
* > any([0, '', false]) |
770
|
|
|
* false |
771
|
|
|
* |
772
|
|
|
* > any([1, null, 3]) |
773
|
|
|
* true |
774
|
|
|
* |
775
|
|
|
* @return boolean |
776
|
|
|
* @deprecated Use iterable($iterable)->any($strategy), will be removed in version 3.0 |
777
|
|
|
*/ |
778
|
|
View Code Duplication |
function any() |
|
|
|
|
779
|
|
|
{ |
780
|
|
|
$args = func_get_args(); |
781
|
|
|
switch (sizeof($args)) { |
782
|
|
|
case 1: |
783
|
|
|
$strategy = null; |
784
|
|
|
$iterable = $args[0]; |
785
|
|
|
break; |
786
|
|
|
|
787
|
|
|
case 2: |
788
|
|
|
$strategy = $args[0]; |
789
|
|
|
$iterable = $args[1]; |
790
|
|
|
break; |
791
|
|
|
|
792
|
|
|
default: |
793
|
|
|
throw new \InvalidArgumentException('any requires either one (iterable) or two (strategy, iterable) arguments'); |
794
|
|
|
} |
795
|
|
|
|
796
|
|
|
if (!($iterable instanceof AllInterface)) { |
797
|
|
|
$iterable = iterable($iterable); |
798
|
|
|
} |
799
|
|
|
|
800
|
|
|
return $iterable->any($strategy); |
801
|
|
|
} |
802
|
|
|
|
803
|
|
|
/** |
804
|
|
|
* Returns true when all elements of $iterable are not empty, otherwise returns false |
805
|
|
|
* |
806
|
|
|
* An optional $strategy may be given to specify the value which is used |
807
|
|
|
* to determine weather the element evaluates to true. When no $strategy is |
808
|
|
|
* given, the identity function is used, i.e. the value of the element |
809
|
|
|
* itself is used to determine weather the element evaluates to true. |
810
|
|
|
* |
811
|
|
|
* Following the optional $strategy, an $iterable may be given. Its type may |
812
|
|
|
* be either array, string, or \Iterator. When no $iterable is given, true |
813
|
|
|
* is returned. |
814
|
|
|
* |
815
|
|
|
* > all([1, 'hello world', true]) |
816
|
|
|
* true |
817
|
|
|
* |
818
|
|
|
* > all([1, null, 3]) |
819
|
|
|
* false |
820
|
|
|
* |
821
|
|
|
* @return boolean |
822
|
|
|
* @deprecated Use iterable($iterable)->all($strategy), will be removed in version 3.0 |
823
|
|
|
*/ |
824
|
|
View Code Duplication |
function all() |
|
|
|
|
825
|
|
|
{ |
826
|
|
|
$args = func_get_args(); |
827
|
|
|
switch (sizeof($args)) { |
828
|
|
|
case 1: |
829
|
|
|
$strategy = null; |
830
|
|
|
$iterable = $args[0]; |
831
|
|
|
break; |
832
|
|
|
|
833
|
|
|
case 2: |
834
|
|
|
$strategy = $args[0]; |
835
|
|
|
$iterable = $args[1]; |
836
|
|
|
break; |
837
|
|
|
|
838
|
|
|
default: |
839
|
|
|
throw new \InvalidArgumentException('all requires either one (iterable) or two (strategy, iterable) arguments'); |
840
|
|
|
} |
841
|
|
|
|
842
|
|
|
if (!($iterable instanceof AllInterface)) { |
843
|
|
|
$iterable = iterable($iterable); |
844
|
|
|
} |
845
|
|
|
|
846
|
|
|
return $iterable->all($strategy); |
847
|
|
|
} |
848
|
|
|
|
849
|
|
|
/** |
850
|
|
|
* Make an iterator that contains a slice of $iterable |
851
|
|
|
* |
852
|
|
|
* The parameters $start and $end determine the range that will be taken |
853
|
|
|
* from the $iterable. These values may be negative, in which case they |
854
|
|
|
* will indicate elements in $iterable starting at the end. |
855
|
|
|
* |
856
|
|
|
* > slice(['a', 'b', 'c', 'd', 'e', 1] |
857
|
|
|
* 'b', 'c', 'd', 'e' |
858
|
|
|
* |
859
|
|
|
* > slice(['a', 'b', 'c', 'd', 'e', -1] |
860
|
|
|
* 'e' |
861
|
|
|
* |
862
|
|
|
* > slice(['a', 'b', 'c', 'd', 'e', 1, 2] |
863
|
|
|
* 'b' |
864
|
|
|
* |
865
|
|
|
* > slice(['a', 'b', 'c', 'd', 'e', 1, -1] |
866
|
|
|
* 'b', 'c', 'd' |
867
|
|
|
* |
868
|
|
|
* @param array|string|\Iterator $iterable |
869
|
|
|
* @param int $start |
870
|
|
|
* @param null|int $end |
871
|
|
|
* @return SliceIterator |
872
|
|
|
* @deprecated Use iterable($iterable)->slice($start, $end), will be removed in version 3.0 |
873
|
|
|
*/ |
874
|
|
|
function slice($iterable, $start, $end = null) |
875
|
|
|
{ |
876
|
|
|
if (!($iterable instanceof SliceInterface)) { |
877
|
|
|
$iterable = iterable($iterable); |
878
|
|
|
} |
879
|
|
|
|
880
|
|
|
return $iterable->slice($start, $end); |
881
|
|
|
} |
882
|
|
|
|
883
|
|
|
/** |
884
|
|
|
* Returns the first element of $iterable or returns $default when $iterable is empty |
885
|
|
|
* |
886
|
|
|
* > first([1, 2, 3]) |
887
|
|
|
* 1 |
888
|
|
|
* |
889
|
|
|
* > first([]) |
890
|
|
|
* null |
891
|
|
|
* |
892
|
|
|
* @param array|string|\Iterator $iterable |
893
|
|
|
* @param mixed $default |
894
|
|
|
* @return mixed |
895
|
|
|
* @deprecated Use iterable($iterable)->first($default), will be removed in version 3.0 |
896
|
|
|
*/ |
897
|
|
|
function first($iterable, $default = null) |
898
|
|
|
{ |
899
|
|
|
if (!($iterable instanceof FirstInterface)) { |
900
|
|
|
$iterable = iterable($iterable); |
901
|
|
|
} |
902
|
|
|
|
903
|
|
|
return $iterable->first($default); |
904
|
|
|
} |
905
|
|
|
|
906
|
|
|
/** |
907
|
|
|
* Returns the key of the first element of $iterable or returns $default when $iterable is empty |
908
|
|
|
* |
909
|
|
|
* > first_key([1, 2, 3]) |
910
|
|
|
* 0 |
911
|
|
|
* |
912
|
|
|
* > first_key([]) |
913
|
|
|
* null |
914
|
|
|
* |
915
|
|
|
* @param array|string|\Iterator $iterable |
916
|
|
|
* @param mixed $default |
917
|
|
|
* @return mixed |
918
|
|
|
* @deprecated Use iterable($iterable)->firstKey($default), will be removed in version 3.0 |
919
|
|
|
*/ |
920
|
|
|
function first_key($iterable, $default = null) |
921
|
|
|
{ |
922
|
|
|
if (!($iterable instanceof FirstInterface)) { |
923
|
|
|
$iterable = iterable($iterable); |
924
|
|
|
} |
925
|
|
|
|
926
|
|
|
return $iterable->firstKey($default); |
927
|
|
|
} |
928
|
|
|
|
929
|
|
|
/** |
930
|
|
|
* Returns the last element of $iterable or returns $default when $iterable is empty |
931
|
|
|
* |
932
|
|
|
* > last([1, 2, 3]) |
933
|
|
|
* 3 |
934
|
|
|
* |
935
|
|
|
* > last([]) |
936
|
|
|
* null |
937
|
|
|
* |
938
|
|
|
* @param array|string|\Iterator $iterable |
939
|
|
|
* @param mixed $default |
940
|
|
|
* @return mixed |
941
|
|
|
* @deprecated Use iterable($iterable)->last($default), will be removed in version 3.0 |
942
|
|
|
*/ |
943
|
|
|
function last($iterable, $default = null) |
944
|
|
|
{ |
945
|
|
|
if (!($iterable instanceof LastInterface)) { |
946
|
|
|
$iterable = iterable($iterable); |
947
|
|
|
} |
948
|
|
|
|
949
|
|
|
return $iterable->last($default); |
950
|
|
|
} |
951
|
|
|
|
952
|
|
|
/** |
953
|
|
|
* Returns the key of the last element of $iterable or returns $default when $iterable is empty |
954
|
|
|
* |
955
|
|
|
* > last_key([1, 2, 3]) |
956
|
|
|
* 2 |
957
|
|
|
* |
958
|
|
|
* > last_key([]) |
959
|
|
|
* null |
960
|
|
|
* |
961
|
|
|
* @param array|string|\Iterator $iterable |
962
|
|
|
* @param mixed $default |
963
|
|
|
* @return mixed |
964
|
|
|
* @deprecated Use iterable($iterable)->lastKey($default), will be removed in version 3.0 |
965
|
|
|
*/ |
966
|
|
|
function last_key($iterable, $default = null) |
967
|
|
|
{ |
968
|
|
|
if (!($iterable instanceof LastInterface)) { |
969
|
|
|
$iterable = iterable($iterable); |
970
|
|
|
} |
971
|
|
|
|
972
|
|
|
return $iterable->lastKey($default); |
973
|
|
|
} |
974
|
|
|
|
975
|
|
|
/** |
976
|
|
|
* Returns an FiniteIterableInterface, providing a fluent interface to itertools |
977
|
|
|
* |
978
|
|
|
* > iterable([1, 2, 3])->filter(...)->map(...)->first(...) |
979
|
|
|
* |
980
|
|
|
* @param array|string|\Iterator $iterable |
981
|
|
|
* @return FiniteIterableInterface |
982
|
|
|
*/ |
983
|
|
|
function iterable($iterable) |
984
|
|
|
{ |
985
|
425 |
|
if ($iterable instanceof FiniteIterableInterface) { |
986
|
2 |
|
return $iterable; |
987
|
|
|
} |
988
|
|
|
|
989
|
425 |
|
return new IterableIterator(Conversions::mixedToIterator($iterable)); |
990
|
|
|
} |
991
|
|
|
|
This function has been deprecated. The supplier of the file has supplied an explanatory message.
The explanatory message should give you some clue as to whether and when the function will be removed from the class and what other function to use instead.