1
|
|
|
<?php |
2
|
|
|
|
3
|
|
|
namespace Pinq; |
4
|
|
|
|
5
|
|
|
use Pinq\Iterators\IIteratorScheme; |
6
|
|
|
|
7
|
|
|
/** |
8
|
|
|
* The standard traversable class, fully implements the traversable API |
9
|
|
|
* using iterators to achieve lazy evaluation |
10
|
|
|
* |
11
|
|
|
* @author Elliot Levin <[email protected]> |
12
|
|
|
*/ |
13
|
|
|
class Traversable implements ITraversable, Interfaces\IOrderedTraversable |
14
|
|
|
{ |
15
|
|
|
/** |
16
|
|
|
* The iterator scheme used in the traversable instance. |
17
|
|
|
* |
18
|
|
|
* @var IIteratorScheme |
19
|
|
|
*/ |
20
|
|
|
protected $scheme; |
21
|
|
|
|
22
|
|
|
/** |
23
|
|
|
* The source traversable. |
24
|
|
|
* |
25
|
|
|
* @var Traversable|null |
26
|
|
|
*/ |
27
|
|
|
protected $source; |
28
|
|
|
|
29
|
|
|
/** |
30
|
|
|
* The element iterator for the traversable. |
31
|
|
|
* |
32
|
|
|
* @var \Traversable |
33
|
|
|
*/ |
34
|
|
|
protected $elements; |
35
|
|
|
|
36
|
|
|
public function __construct($elements = [], IIteratorScheme $scheme = null, Traversable $source = null) |
37
|
|
|
{ |
38
|
|
|
$this->scheme = $scheme ?: Iterators\SchemeProvider::getDefault(); |
39
|
|
|
$this->source = $source; |
40
|
|
|
$this->elements = $this->scheme->toIterator($elements); |
41
|
|
|
} |
42
|
|
|
|
43
|
|
|
/** |
44
|
|
|
* Constructs a new traversable object from the supplied elements. |
45
|
|
|
* |
46
|
|
|
* @param array|\Traversable $elements |
47
|
|
|
* @param IIteratorScheme|null $scheme |
48
|
|
|
* @param Traversable|null $source |
49
|
|
|
* |
50
|
|
|
* @return ITraversable |
51
|
|
|
*/ |
52
|
|
|
public static function from($elements, IIteratorScheme $scheme = null, Traversable $source = null) |
53
|
|
|
{ |
54
|
|
|
return new static($elements, $scheme, $source); |
55
|
|
|
} |
56
|
|
|
|
57
|
|
|
/** |
58
|
|
|
* Returns a callable for the traversable constructor. |
59
|
|
|
* |
60
|
|
|
* @param IIteratorScheme|null $scheme |
61
|
|
|
* @param Traversable|null $source |
62
|
|
|
* |
63
|
|
|
* @return callable |
64
|
|
|
*/ |
65
|
|
|
public static function factory(IIteratorScheme $scheme = null, Traversable $source = null) |
66
|
|
|
{ |
67
|
|
|
//static:: doesn't work in closures? |
68
|
|
|
$static = get_called_class(); |
69
|
|
|
|
70
|
|
|
return function ($elements) use ($static, $scheme, $source) { |
71
|
|
|
return $static::from($elements, $scheme, $source); |
72
|
|
|
}; |
73
|
|
|
} |
74
|
|
|
|
75
|
|
|
/** |
76
|
|
|
* Returns a callable factory to construct an equivalent |
77
|
|
|
* instance with the supplied elements. |
78
|
|
|
* |
79
|
|
|
* @return callable |
80
|
|
|
*/ |
81
|
|
|
final protected function scopedSelfFactory() |
82
|
|
|
{ |
83
|
|
|
return function ($elements) { |
84
|
|
|
return $this->constructScopedSelf($elements); |
85
|
|
|
}; |
86
|
|
|
} |
87
|
|
|
|
88
|
|
|
/** |
89
|
|
|
* Returns a new instance of the traversable with the scoped elements |
90
|
|
|
* and same scheme and source. |
91
|
|
|
* |
92
|
|
|
* @param array|\Traversable $elements |
93
|
|
|
* |
94
|
|
|
* @return static |
95
|
|
|
*/ |
96
|
|
|
protected function constructScopedSelf($elements) |
97
|
|
|
{ |
98
|
|
|
return static::from($elements, $this->scheme, $this->source ?: $this); |
99
|
|
|
} |
100
|
|
|
|
101
|
|
|
public function isSource() |
102
|
|
|
{ |
103
|
|
|
return $this->source === null; |
104
|
|
|
} |
105
|
|
|
|
106
|
|
|
public function getSource() |
107
|
|
|
{ |
108
|
|
|
return $this->source ?: $this; |
109
|
|
|
} |
110
|
|
|
|
111
|
|
|
public function asArray() |
112
|
|
|
{ |
113
|
|
|
return $this->scheme->toArray($this->elements); |
114
|
|
|
} |
115
|
|
|
|
116
|
|
|
public function getIterator() |
117
|
|
|
{ |
118
|
|
|
return $this->scheme->arrayCompatibleIterator($this->getTrueIterator()); |
119
|
|
|
} |
120
|
|
|
|
121
|
|
|
public function getTrueIterator() |
122
|
|
|
{ |
123
|
|
|
return $this->elements; |
124
|
|
|
} |
125
|
|
|
|
126
|
|
|
public function getIteratorScheme() |
127
|
|
|
{ |
128
|
|
|
return $this->scheme; |
129
|
|
|
} |
130
|
|
|
|
131
|
|
|
public function asTraversable() |
132
|
|
|
{ |
133
|
|
|
return $this; |
134
|
|
|
} |
135
|
|
|
|
136
|
|
|
public function asCollection() |
137
|
|
|
{ |
138
|
|
|
return new Collection($this->elements, $this->scheme); |
139
|
|
|
} |
140
|
|
|
|
141
|
|
|
/** |
142
|
|
|
* @return Iterators\IOrderedMap |
143
|
|
|
*/ |
144
|
|
|
protected function asOrderedMap() |
145
|
|
|
{ |
146
|
|
|
return $this->elements instanceof Iterators\IOrderedMap ? |
147
|
|
|
$this->elements : $this->scheme->createOrderedMap($this->elements); |
148
|
|
|
} |
149
|
|
|
|
150
|
|
|
public function iterate(callable $function) |
151
|
|
|
{ |
152
|
|
|
$this->scheme->walk($this->elements, $function); |
153
|
|
|
} |
154
|
|
|
|
155
|
|
|
// <editor-fold defaultstate="collapsed" desc="Querying"> |
156
|
|
|
|
157
|
|
|
public function first() |
158
|
|
|
{ |
159
|
|
|
foreach ($this->elements as $value) { |
160
|
|
|
return $value; |
161
|
|
|
} |
162
|
|
|
|
163
|
|
|
return null; |
164
|
|
|
} |
165
|
|
|
|
166
|
|
|
public function last() |
167
|
|
|
{ |
168
|
|
|
$value = null; |
169
|
|
|
|
170
|
|
|
foreach ($this->elements as $value) { |
171
|
|
|
|
172
|
|
|
} |
173
|
|
|
|
174
|
|
|
return $value; |
175
|
|
|
} |
176
|
|
|
|
177
|
|
|
public function where(callable $predicate) |
178
|
|
|
{ |
179
|
|
|
return $this->constructScopedSelf( |
180
|
|
|
$this->scheme->filterIterator( |
181
|
|
|
$this->elements, |
182
|
|
|
$predicate |
183
|
|
|
) |
184
|
|
|
); |
185
|
|
|
} |
186
|
|
|
|
187
|
|
|
public function orderByAscending(callable $function) |
188
|
|
|
{ |
189
|
|
|
return $this->constructScopedSelf( |
190
|
|
|
$this->scheme->orderedIterator( |
191
|
|
|
$this->elements, |
192
|
|
|
$function, |
193
|
|
|
true |
194
|
|
|
) |
195
|
|
|
); |
196
|
|
|
} |
197
|
|
|
|
198
|
|
|
public function orderByDescending(callable $function) |
199
|
|
|
{ |
200
|
|
|
return $this->constructScopedSelf( |
201
|
|
|
$this->scheme->orderedIterator( |
202
|
|
|
$this->elements, |
203
|
|
|
$function, |
204
|
|
|
false |
205
|
|
|
) |
206
|
|
|
); |
207
|
|
|
} |
208
|
|
|
|
209
|
|
|
public function orderBy(callable $function, $direction) |
210
|
|
|
{ |
211
|
|
|
return $direction === Direction::DESCENDING ? |
212
|
|
|
$this->orderByDescending($function) : $this->orderByAscending($function); |
213
|
|
|
} |
214
|
|
|
|
215
|
|
|
/** |
216
|
|
|
* Verifies that the traversable is ordered. |
217
|
|
|
* |
218
|
|
|
* @param string $method The called method name |
219
|
|
|
* |
220
|
|
|
* @return Iterators\IOrderedIterator |
221
|
|
|
* @throws PinqException |
222
|
|
|
*/ |
223
|
|
|
private function validateIsOrdered($method) |
224
|
|
|
{ |
225
|
|
|
$innerIterator = $this->elements; |
226
|
|
|
if (!($innerIterator instanceof Iterators\IOrderedIterator)) { |
227
|
|
|
throw new PinqException( |
228
|
|
|
'Invalid call to %s: %s::%s must be called first.', |
229
|
|
|
$method, |
230
|
|
|
__CLASS__, |
231
|
|
|
'orderBy'); |
232
|
|
|
} |
233
|
|
|
|
234
|
|
|
return $innerIterator; |
235
|
|
|
} |
236
|
|
|
|
237
|
|
|
public function thenBy(callable $function, $direction) |
238
|
|
|
{ |
239
|
|
|
return $this->constructScopedSelf( |
240
|
|
|
$this->validateIsOrdered(__METHOD__)->thenOrderBy( |
241
|
|
|
$function, |
242
|
|
|
$direction !== Direction::DESCENDING |
243
|
|
|
) |
244
|
|
|
); |
245
|
|
|
} |
246
|
|
|
|
247
|
|
|
public function thenByAscending(callable $function) |
248
|
|
|
{ |
249
|
|
|
return $this->constructScopedSelf( |
250
|
|
|
$this->validateIsOrdered(__METHOD__) |
251
|
|
|
->thenOrderBy($function, true) |
252
|
|
|
); |
253
|
|
|
} |
254
|
|
|
|
255
|
|
|
public function thenByDescending(callable $function) |
256
|
|
|
{ |
257
|
|
|
return $this->constructScopedSelf( |
258
|
|
|
$this->validateIsOrdered(__METHOD__) |
259
|
|
|
->thenOrderBy($function, false) |
260
|
|
|
); |
261
|
|
|
} |
262
|
|
|
|
263
|
|
|
public function skip($amount) |
264
|
|
|
{ |
265
|
|
|
return $this->constructScopedSelf( |
266
|
|
|
$this->scheme->rangeIterator( |
267
|
|
|
$this->elements, |
268
|
|
|
$amount, |
269
|
|
|
null |
270
|
|
|
) |
271
|
|
|
); |
272
|
|
|
} |
273
|
|
|
|
274
|
|
|
public function take($amount) |
275
|
|
|
{ |
276
|
|
|
return $this->constructScopedSelf( |
277
|
|
|
$this->scheme->rangeIterator( |
278
|
|
|
$this->elements, |
279
|
|
|
0, |
280
|
|
|
$amount |
281
|
|
|
) |
282
|
|
|
); |
283
|
|
|
} |
284
|
|
|
|
285
|
|
|
public function slice($start, $amount) |
286
|
|
|
{ |
287
|
|
|
return $this->constructScopedSelf( |
288
|
|
|
$this->scheme->rangeIterator( |
289
|
|
|
$this->elements, |
290
|
|
|
$start, |
291
|
|
|
$amount |
292
|
|
|
) |
293
|
|
|
); |
294
|
|
|
} |
295
|
|
|
|
296
|
|
|
public function indexBy(callable $function) |
297
|
|
|
{ |
298
|
|
|
return $this->constructScopedSelf( |
299
|
|
|
$this->scheme->uniqueKeyIterator( |
300
|
|
|
$this->scheme->projectionIterator( |
301
|
|
|
$this->elements, |
302
|
|
|
$function, |
303
|
|
|
null |
304
|
|
|
) |
305
|
|
|
) |
306
|
|
|
); |
307
|
|
|
} |
308
|
|
|
|
309
|
|
View Code Duplication |
public function keys() |
|
|
|
|
310
|
|
|
{ |
311
|
|
|
return $this->constructScopedSelf( |
312
|
|
|
$this->scheme->reindexerIterator( |
313
|
|
|
$this->scheme->projectionIterator( |
314
|
|
|
$this->elements, |
315
|
|
|
null, |
316
|
|
|
function ($value, $key) { |
317
|
|
|
return $key; |
318
|
|
|
} |
319
|
|
|
) |
320
|
|
|
) |
321
|
|
|
); |
322
|
|
|
} |
323
|
|
|
|
324
|
|
|
public function reindex() |
325
|
|
|
{ |
326
|
|
|
return $this->constructScopedSelf( |
327
|
|
|
$this->scheme->reindexerIterator($this->elements) |
328
|
|
|
); |
329
|
|
|
} |
330
|
|
|
|
331
|
|
|
public function groupBy(callable $function) |
332
|
|
|
{ |
333
|
|
|
return $this->constructScopedSelf( |
334
|
|
|
$this->scheme->groupedIterator( |
335
|
|
|
$this->elements, |
336
|
|
|
$function, |
337
|
|
|
$this->scopedSelfFactory() |
338
|
|
|
) |
339
|
|
|
); |
340
|
|
|
} |
341
|
|
|
|
342
|
|
View Code Duplication |
public function join($values) |
|
|
|
|
343
|
|
|
{ |
344
|
|
|
return new Connectors\JoiningTraversable( |
345
|
|
|
$this->scheme, |
346
|
|
|
$this->scheme->joinIterator( |
347
|
|
|
$this->elements, |
348
|
|
|
$this->scheme->toIterator($values) |
349
|
|
|
), |
350
|
|
|
$this->scopedSelfFactory()); |
351
|
|
|
} |
352
|
|
|
|
353
|
|
View Code Duplication |
public function groupJoin($values) |
|
|
|
|
354
|
|
|
{ |
355
|
|
|
return new Connectors\JoiningTraversable( |
356
|
|
|
$this->scheme, |
357
|
|
|
$this->scheme->groupJoinIterator( |
358
|
|
|
$this->elements, |
359
|
|
|
$this->scheme->toIterator($values), |
360
|
|
|
$this->scopedSelfFactory() |
361
|
|
|
), |
362
|
|
|
$this->scopedSelfFactory()); |
363
|
|
|
} |
364
|
|
|
|
365
|
|
|
public function unique() |
366
|
|
|
{ |
367
|
|
|
return $this->constructScopedSelf($this->scheme->uniqueIterator($this->elements)); |
368
|
|
|
} |
369
|
|
|
|
370
|
|
|
public function select(callable $function) |
371
|
|
|
{ |
372
|
|
|
return $this->constructScopedSelf( |
373
|
|
|
$this->scheme->projectionIterator( |
374
|
|
|
$this->elements, |
375
|
|
|
null, |
376
|
|
|
$function |
377
|
|
|
) |
378
|
|
|
); |
379
|
|
|
} |
380
|
|
|
|
381
|
|
View Code Duplication |
public function selectMany(callable $function) |
|
|
|
|
382
|
|
|
{ |
383
|
|
|
$projectionIterator = |
384
|
|
|
$this->scheme->projectionIterator( |
385
|
|
|
$this->elements, |
386
|
|
|
null, |
387
|
|
|
$function |
388
|
|
|
); |
389
|
|
|
|
390
|
|
|
return $this->constructScopedSelf($this->scheme->flattenedIterator($projectionIterator)); |
391
|
|
|
} |
392
|
|
|
|
393
|
|
|
// </editor-fold> |
394
|
|
|
|
395
|
|
|
// <editor-fold defaultstate="collapsed" desc="Set Operations"> |
396
|
|
|
|
397
|
|
|
public function union($values) |
398
|
|
|
{ |
399
|
|
|
return $this->constructScopedSelf( |
400
|
|
|
$this->scheme->unionIterator( |
401
|
|
|
$this->elements, |
402
|
|
|
$this->scheme->toIterator($values) |
403
|
|
|
) |
404
|
|
|
); |
405
|
|
|
} |
406
|
|
|
|
407
|
|
|
public function intersect($values) |
408
|
|
|
{ |
409
|
|
|
return $this->constructScopedSelf( |
410
|
|
|
$this->scheme->intersectionIterator( |
411
|
|
|
$this->elements, |
412
|
|
|
$this->scheme->toIterator($values) |
413
|
|
|
) |
414
|
|
|
); |
415
|
|
|
} |
416
|
|
|
|
417
|
|
|
public function difference($values) |
418
|
|
|
{ |
419
|
|
|
return $this->constructScopedSelf( |
420
|
|
|
$this->scheme->differenceIterator( |
421
|
|
|
$this->elements, |
422
|
|
|
$this->scheme->toIterator($values) |
423
|
|
|
) |
424
|
|
|
); |
425
|
|
|
} |
426
|
|
|
|
427
|
|
|
// </editor-fold> |
428
|
|
|
|
429
|
|
|
// <editor-fold defaultstate="collapsed" desc="Multiset Operations"> |
430
|
|
|
|
431
|
|
|
public function append($values) |
432
|
|
|
{ |
433
|
|
|
return $this->constructScopedSelf( |
434
|
|
|
$this->scheme->appendIterator( |
435
|
|
|
$this->elements, |
436
|
|
|
$this->scheme->toIterator($values) |
437
|
|
|
) |
438
|
|
|
); |
439
|
|
|
} |
440
|
|
|
|
441
|
|
|
public function whereIn($values) |
442
|
|
|
{ |
443
|
|
|
return $this->constructScopedSelf( |
444
|
|
|
$this->scheme->whereInIterator( |
445
|
|
|
$this->elements, |
446
|
|
|
$this->scheme->toIterator($values) |
447
|
|
|
) |
448
|
|
|
); |
449
|
|
|
} |
450
|
|
|
|
451
|
|
|
public function except($values) |
452
|
|
|
{ |
453
|
|
|
return $this->constructScopedSelf( |
454
|
|
|
$this->scheme->exceptIterator( |
455
|
|
|
$this->elements, |
456
|
|
|
$this->scheme->toIterator($values) |
457
|
|
|
) |
458
|
|
|
); |
459
|
|
|
} |
460
|
|
|
|
461
|
|
|
// </editor-fold> |
462
|
|
|
|
463
|
|
|
// <editor-fold defaultstate="collapsed" desc="Array Access"> |
464
|
|
|
|
465
|
|
|
public function offsetExists($index) |
466
|
|
|
{ |
467
|
|
|
foreach ($this->keys() as $key) { |
468
|
|
|
if ($key === $index) { |
469
|
|
|
return true; |
470
|
|
|
} |
471
|
|
|
} |
472
|
|
|
|
473
|
|
|
return false; |
474
|
|
|
} |
475
|
|
|
|
476
|
|
|
public function offsetGet($index) |
477
|
|
|
{ |
478
|
|
|
foreach ($this->select(function ($value, $key) { return [$key, $value]; }) as $element) { |
479
|
|
|
if ($element[0] === $index) { |
480
|
|
|
return $element[1]; |
481
|
|
|
} |
482
|
|
|
} |
483
|
|
|
|
484
|
|
|
return false; |
485
|
|
|
} |
486
|
|
|
|
487
|
|
|
public function offsetSet($index, $value) |
488
|
|
|
{ |
489
|
|
|
throw PinqException::notSupported(__METHOD__); |
490
|
|
|
} |
491
|
|
|
|
492
|
|
|
public function offsetUnset($index) |
493
|
|
|
{ |
494
|
|
|
throw PinqException::notSupported(__METHOD__); |
495
|
|
|
} |
496
|
|
|
|
497
|
|
|
// </editor-fold> |
498
|
|
|
|
499
|
|
|
// <editor-fold defaultstate="collapsed" desc="Aggregates"> |
500
|
|
|
|
501
|
|
|
public function count() |
502
|
|
|
{ |
503
|
|
|
if($this->elements instanceof \Countable) { |
504
|
|
|
return $this->elements->count(); |
505
|
|
|
} |
506
|
|
|
|
507
|
|
|
$count = 0; |
508
|
|
|
|
509
|
|
|
foreach($this->elements as $value) { |
510
|
|
|
$count++; |
511
|
|
|
} |
512
|
|
|
|
513
|
|
|
return $count; |
514
|
|
|
} |
515
|
|
|
|
516
|
|
|
public function isEmpty() |
517
|
|
|
{ |
518
|
|
|
foreach ($this->elements as $value) { |
519
|
|
|
return false; |
520
|
|
|
} |
521
|
|
|
|
522
|
|
|
return true; |
523
|
|
|
} |
524
|
|
|
|
525
|
|
|
public function contains($value) |
526
|
|
|
{ |
527
|
|
|
foreach ($this->elements as $containedValue) { |
528
|
|
|
if ($containedValue === $value) { |
529
|
|
|
return true; |
530
|
|
|
} |
531
|
|
|
} |
532
|
|
|
|
533
|
|
|
return false; |
534
|
|
|
} |
535
|
|
|
|
536
|
|
|
public function aggregate(callable $function) |
537
|
|
|
{ |
538
|
|
|
$hasValue = false; |
539
|
|
|
$aggregateValue = null; |
540
|
|
|
|
541
|
|
|
foreach ($this->elements as $value) { |
542
|
|
|
if (!$hasValue) { |
543
|
|
|
$aggregateValue = $value; |
544
|
|
|
$hasValue = true; |
545
|
|
|
continue; |
546
|
|
|
} |
547
|
|
|
|
548
|
|
|
$aggregateValue = $function($aggregateValue, $value); |
549
|
|
|
} |
550
|
|
|
|
551
|
|
|
return $aggregateValue; |
552
|
|
|
} |
553
|
|
|
|
554
|
|
|
private function mapIterator(callable $function = null) |
555
|
|
|
{ |
556
|
|
|
if ($function === null) { |
557
|
|
|
return $this->elements; |
558
|
|
|
} else { |
559
|
|
|
return $this->scheme->projectionIterator( |
560
|
|
|
$this->elements, |
561
|
|
|
null, |
562
|
|
|
$function |
563
|
|
|
); |
564
|
|
|
} |
565
|
|
|
} |
566
|
|
|
|
567
|
|
View Code Duplication |
public function maximum(callable $function = null) |
|
|
|
|
568
|
|
|
{ |
569
|
|
|
$max = null; |
570
|
|
|
|
571
|
|
|
foreach ($this->mapIterator($function) as $value) { |
572
|
|
|
if ($value > $max) { |
573
|
|
|
$max = $value; |
574
|
|
|
} |
575
|
|
|
} |
576
|
|
|
|
577
|
|
|
return $max; |
578
|
|
|
} |
579
|
|
|
|
580
|
|
|
public function minimum(callable $function = null) |
581
|
|
|
{ |
582
|
|
|
$min = null; |
583
|
|
|
$first = true; |
584
|
|
|
|
585
|
|
|
foreach ($this->mapIterator($function) as $value) { |
586
|
|
|
if ($value < $min || $first) { |
587
|
|
|
$min = $value; |
588
|
|
|
$first = false; |
589
|
|
|
} |
590
|
|
|
} |
591
|
|
|
|
592
|
|
|
return $min; |
593
|
|
|
} |
594
|
|
|
|
595
|
|
View Code Duplication |
public function sum(callable $function = null) |
|
|
|
|
596
|
|
|
{ |
597
|
|
|
$sum = null; |
598
|
|
|
|
599
|
|
|
foreach ($this->mapIterator($function) as $value) { |
600
|
|
|
$sum += $value; |
601
|
|
|
} |
602
|
|
|
|
603
|
|
|
return $sum; |
604
|
|
|
} |
605
|
|
|
|
606
|
|
|
public function average(callable $function = null) |
607
|
|
|
{ |
608
|
|
|
$sum = null; |
609
|
|
|
$count = 0; |
610
|
|
|
|
611
|
|
|
foreach ($this->mapIterator($function) as $value) { |
612
|
|
|
$sum += $value; |
613
|
|
|
$count++; |
614
|
|
|
} |
615
|
|
|
|
616
|
|
|
return $count === 0 ? null : $sum / $count; |
617
|
|
|
} |
618
|
|
|
|
619
|
|
|
public function all(callable $function = null) |
620
|
|
|
{ |
621
|
|
|
foreach ($this->mapIterator($function) as $value) { |
622
|
|
|
if (!$value) { |
623
|
|
|
return false; |
624
|
|
|
} |
625
|
|
|
} |
626
|
|
|
|
627
|
|
|
return true; |
628
|
|
|
} |
629
|
|
|
|
630
|
|
|
public function any(callable $function = null) |
631
|
|
|
{ |
632
|
|
|
foreach ($this->mapIterator($function) as $value) { |
633
|
|
|
if ($value) { |
634
|
|
|
return true; |
635
|
|
|
} |
636
|
|
|
} |
637
|
|
|
|
638
|
|
|
return false; |
639
|
|
|
} |
640
|
|
|
|
641
|
|
|
public function implode($delimiter, callable $function = null) |
642
|
|
|
{ |
643
|
|
|
$string = ''; |
644
|
|
|
|
645
|
|
|
foreach ($this->mapIterator($function) as $value) { |
646
|
|
|
$string .= $delimiter . $value; |
647
|
|
|
} |
648
|
|
|
|
649
|
|
|
return $string === '' ? '' : substr($string, strlen($delimiter)); |
650
|
|
|
} |
651
|
|
|
|
652
|
|
|
// </editor-fold> |
653
|
|
|
} |
654
|
|
|
|
Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.
You can also find more detailed suggestions in the “Code” section of your repository.