GitHub Access Token became invalid

It seems like the GitHub access token used for retrieving details about this repository from GitHub became invalid. This might prevent certain types of inspections from being run (in particular, everything related to pull requests).
Please ask an admin of your repository to re-new the access token on this website.

EnumerablePagination::lastIndexOf()   A
last analyzed

Complexity

Conditions 3
Paths 3

Size

Total Lines 9
Code Lines 6

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 3
eloc 6
nc 3
nop 1
dl 0
loc 9
rs 9.6666
c 0
b 0
f 0
1
<?php
2
3
/**
4
 * EnumerablePagination trait of Enumerable class.
5
 * @author Alexander Prokhorov
6
 * @license Simplified BSD
7
 * @link https://github.com/Athari/YaLinqo YaLinqo on GitHub
8
 */
9
10
namespace YaLinqo;
11
12
/**
13
 * Trait of {@link Enumerable} containing pagination methods.
14
 * @package YaLinqo
15
 */
16
trait EnumerablePagination
17
{
18
    /**
19
     * Returns the value at a specified key in a sequence.
20
     * <p><b>Syntax</b>: elementAt (key)
21
     * <p>Returns the value at a specified key in a sequence.
22
     * <p>If the type of source iterator implements {@link ArrayAccess}, that implementation is used to obtain the value at the specified key. Otherwise, this method obtains the specified value.
23
     * <p>This method throws an exception if key is not found. To instead return a default value when the specified key is not found, use the {@link elementAtOrDefault} method.
24
     * @param mixed $key The key of the value to retrieve.
25
     * @throws \UnexpectedValueException If sequence does not contain value with specified key.
26
     * @return mixed The value at the key in the source sequence.
27
     * @package YaLinqo\Pagination
28
     */
29
    public function elementAt($key)
30
    {
31
        /** @var $it \Iterator|\ArrayAccess */
32
        $it = $this->getIterator();
33
34
        if ($it instanceof \ArrayAccess) {
35
            if (!$it->offsetExists($key))
36
                throw new \UnexpectedValueException(Errors::NO_KEY);
37
            return $it->offsetGet($key);
38
        }
39
40
        foreach ($it as $k => $v) {
41
            if ($k === $key)
42
                return $v;
43
        }
44
        throw new \UnexpectedValueException(Errors::NO_KEY);
45
    }
46
47
    /**
48
     * Returns the value at a specified key in a sequence or a default value if the key is not found.
49
     * <p><b>Syntax</b>: elementAtOrDefault (key [, default])
50
     * <p>If the type of source iterator implements {@link ArrayAccess}, that implementation is used to obtain the value at the specified key. Otherwise, this method obtains the specified value.
51
     * @param mixed $key The key of the value to retrieve.
52
     * @param mixed $default Value to return if sequence does not contain value with specified key. Default: null.
53
     * @return mixed default value if the key is not found in the source sequence; otherwise, the value at the specified key in the source sequence.
54
     * @package YaLinqo\Pagination
55
     */
56
    public function elementAtOrDefault($key, $default = null)
57
    {
58
        /** @var $it \Iterator|\ArrayAccess */
59
        $it = $this->getIterator();
60
61
        if ($it instanceof \ArrayAccess)
62
            return $it->offsetExists($key) ? $it->offsetGet($key) : $default;
63
64
        foreach ($it as $k => $v) {
65
            if ($k === $key)
66
                return $v;
67
        }
68
        return $default;
69
    }
70
71
    /**
72
     * Returns the first element of a sequence.
73
     * <p><b>Syntax</b>: first ()
74
     * <p>Returns the first element of a sequence.
75
     * <p>The first method throws an exception if source contains no elements. To instead return a default value when the source sequence is empty, use the {@link firstOrDefault} method.
76
     * <p><b>Syntax</b>: first (predicate {(v, k) ==> result})
77
     * <p>Returns the first element in a sequence that satisfies a specified condition.
78
     * <p>The first method throws an exception if no matching element is found in source. To instead return a default value when no matching element is found, use the {@link firstOrDefault} method.
79
     * @param callable|null $predicate {(v, k) ==> result} A function to test each element for a condition. Default: true.
80
     * @throws \UnexpectedValueException If source contains no matching elements.
81
     * @return mixed If predicate is null: the first element in the specified sequence. If predicate is not null: The first element in the sequence that passes the test in the specified predicate function.
82
     * @package YaLinqo\Pagination
83
     */
84
    public function first($predicate = null)
85
    {
86
        $predicate = Utils::createLambda($predicate, 'v,k', Functions::$true);
87
88
        foreach ($this as $k => $v) {
89
            if ($predicate($v, $k))
90
                return $v;
91
        }
92
        throw new \UnexpectedValueException(Errors::NO_MATCHES);
93
    }
94
95
    /**
96
     * Returns the first element of a sequence, or a default value if the sequence contains no elements.
97
     * <p><b>Syntax</b>: firstOrDefault ([default])
98
     * <p>Returns the first element of a sequence, or a default value if the sequence contains no elements.
99
     * <p><b>Syntax</b>: firstOrDefault ([default [, predicate {(v, k) ==> result}]])
100
     * <p>Returns the first element of the sequence that satisfies a condition or a default value if no such element is found.
101
     * <p>If obtaining the default value is a costly operation, use {@link firstOrFallback} method to avoid overhead.
102
     * @param mixed $default A default value.
103
     * @param callable|null $predicate {(v, k) ==> result} A function to test each element for a condition. Default: true.
104
     * @return mixed If predicate is null: default value if source is empty; otherwise, the first element in source. If predicate is not null: default value if source is empty or if no element passes the test specified by predicate; otherwise, the first element in source that passes the test specified by predicate.
105
     * @package YaLinqo\Pagination
106
     */
107
    public function firstOrDefault($default = null, $predicate = null)
108
    {
109
        $predicate = Utils::createLambda($predicate, 'v,k', Functions::$true);
110
111
        foreach ($this as $k => $v) {
112
            if ($predicate($v, $k))
113
                return $v;
114
        }
115
        return $default;
116
    }
117
118
    /**
119
     * Returns the first element of a sequence, or the result of calling a fallback function if the sequence contains no elements.
120
     * <p><b>Syntax</b>: firstOrFallback ([fallback {() ==> value}])
121
     * <p>Returns the first element of a sequence, or the result of calling a fallback function if the sequence contains no elements.
122
     * <p><b>Syntax</b>: firstOrFallback ([fallback {() ==> value} [, predicate {(v, k) ==> result}]])
123
     * <p>Returns the first element of the sequence that satisfies a condition or the result of calling a fallback function if no such element is found.
124
     * <p>The fallback function is not executed if a matching element is found. Use the firstOrFallback method if obtaining the default value is a costly operation to avoid overhead. Otherwise, use {@link firstOrDefault}.
125
     * @param callable $fallback {() ==> value} A fallback function to return the default element.
126
     * @param callable|null $predicate {(v, k) ==> result} A function to test each element for a condition. Default: true.
127
     * @return mixed If predicate is null: the result of calling a fallback function if source is empty; otherwise, the first element in source. If predicate is not null: the result of calling a fallback function if source is empty or if no element passes the test specified by predicate; otherwise, the first element in source that passes the test specified by predicate.
128
     * @package YaLinqo\Pagination
129
     */
130
    public function firstOrFallback($fallback, $predicate = null)
131
    {
132
        $predicate = Utils::createLambda($predicate, 'v,k', Functions::$true);
133
134
        foreach ($this as $k => $v) {
135
            if ($predicate($v, $k))
136
                return $v;
137
        }
138
        return $fallback();
139
    }
140
141
    /**
142
     * Returns the last element of a sequence.
143
     * <p><b>Syntax</b>: last ()
144
     * <p>Returns the last element of a sequence.
145
     * <p>The last method throws an exception if source contains no elements. To instead return a default value when the source sequence is empty, use the {@link lastOrDefault} method.
146
     * <p><b>Syntax</b>: last (predicate {(v, k) ==> result})
147
     * <p>Returns the last element in a sequence that satisfies a specified condition.
148
     * <p>The last method throws an exception if no matching element is found in source. To instead return a default value when no matching element is found, use the {@link lastOrDefault} method.
149
     * @param callable|null $predicate {(v, k) ==> result} A function to test each element for a condition. Default: true.
150
     * @throws \UnexpectedValueException If source contains no matching elements.
151
     * @return mixed If predicate is null: the last element in the specified sequence. If predicate is not null: The last element in the sequence that passes the test in the specified predicate function.
152
     * @package YaLinqo\Pagination
153
     */
154
    public function last($predicate = null)
155
    {
156
        $predicate = Utils::createLambda($predicate, 'v,k', Functions::$true);
157
158
        $found = false;
159
        $value = null;
160
        foreach ($this as $k => $v) {
161
            if ($predicate($v, $k)) {
162
                $found = true;
163
                $value = $v;
164
            }
165
        }
166
        if (!$found)
167
            throw new \UnexpectedValueException(Errors::NO_MATCHES);
168
        return $value;
169
    }
170
171
    /**
172
     * Returns the last element of a sequence, or a default value if the sequence contains no elements.
173
     * <p><b>Syntax</b>: lastOrDefault ([default])
174
     * <p>Returns the last element of a sequence, or a default value if the sequence contains no elements.
175
     * <p><b>Syntax</b>: lastOrDefault ([default [, predicate {(v, k) ==> result}]])
176
     * <p>Returns the last element of the sequence that satisfies a condition or a default value if no such element is found.
177
     * <p>If obtaining the default value is a costly operation, use {@link lastOrFallback} method to avoid overhead.
178
     * @param mixed $default A default value.
179
     * @param callable|null $predicate {(v, k) ==> result} A function to test each element for a condition. Default: true.
180
     * @return mixed If predicate is null: default value if source is empty; otherwise, the last element in source. If predicate is not null: default value if source is empty or if no element passes the test specified by predicate; otherwise, the last element in source that passes the test specified by predicate.
181
     * @package YaLinqo\Pagination
182
     */
183
    public function lastOrDefault($default = null, $predicate = null)
184
    {
185
        $predicate = Utils::createLambda($predicate, 'v,k', Functions::$true);
186
187
        $found = false;
188
        $value = null;
189
        foreach ($this as $k => $v) {
190
            if ($predicate($v, $k)) {
191
                $found = true;
192
                $value = $v;
193
            }
194
        }
195
        return $found ? $value : $default;
196
    }
197
198
    /**
199
     * Returns the last element of a sequence, or the result of calling a fallback function if the sequence contains no elements.
200
     * <p><b>Syntax</b>: lastOrFallback ([fallback {() ==> value}])
201
     * <p>Returns the last element of a sequence, or the result of calling a fallback function if the sequence contains no elements.
202
     * <p><b>Syntax</b>: lastOrFallback ([fallback {() ==> value} [, predicate {(v, k) ==> result}]])
203
     * <p>Returns the last element of the sequence that satisfies a condition or the result of calling a fallback function if no such element is found.
204
     * <p>The fallback function is not executed if a matching element is found. Use the lastOrFallback method if obtaining the default value is a costly operation to avoid overhead. Otherwise, use {@link lastOrDefault}.
205
     * @param callable $fallback {() ==> value} A fallback function to return the default element.
206
     * @param callable|null $predicate {(v, k) ==> result} A function to test each element for a condition. Default: true.
207
     * @return mixed If predicate is null: the result of calling a fallback function if source is empty; otherwise, the last element in source. If predicate is not null: the result of calling a fallback function if source is empty or if no element passes the test specified by predicate; otherwise, the last element in source that passes the test specified by predicate.
208
     * @package YaLinqo\Pagination
209
     */
210
    public function lastOrFallback($fallback, $predicate = null)
211
    {
212
        $predicate = Utils::createLambda($predicate, 'v,k', Functions::$true);
213
214
        $found = false;
215
        $value = null;
216
        foreach ($this as $k => $v) {
217
            if ($predicate($v, $k)) {
218
                $found = true;
219
                $value = $v;
220
            }
221
        }
222
        return $found ? $value : $fallback();
223
    }
224
225
    /**
226
     * Returns the only element of a sequence, and throws an exception if there is not exactly one element in the sequence.
227
     * <p><b>Syntax</b>: single ()
228
     * <p>Returns the only element of a sequence, and throws an exception if there is not exactly one element in the sequence.
229
     * <p>The single method throws an exception if source contains no elements. To instead return a default value when the source sequence is empty, use the {@link singleOrDefault} method.
230
     * <p><b>Syntax</b>: single (predicate {(v, k) ==> result})
231
     * <p>Returns the only element of a sequence that satisfies a specified condition.
232
     * <p>The single method throws an exception if no matching element is found in source. To instead return a default value when no matching element is found, use the {@link singleOrDefault} method.
233
     * @param callable|null $predicate {(v, k) ==> result} A function to test each element for a condition. Default: true.
234
     * @throws \UnexpectedValueException If source contains no matching elements or more than one matching element.
235
     * @return mixed If predicate is null: the single element of the input sequence. If predicate is not null: The single element of the sequence that passes the test in the specified predicate function.
236
     * @package YaLinqo\Pagination
237
     */
238
    public function single($predicate = null)
239
    {
240
        $predicate = Utils::createLambda($predicate, 'v,k', Functions::$true);
241
242
        $found = false;
243
        $value = null;
244
        foreach ($this as $k => $v) {
245
            if ($predicate($v, $k)) {
246
                if ($found)
247
                    throw new \UnexpectedValueException(Errors::MANY_MATCHES);
248
                $found = true;
249
                $value = $v;
250
            }
251
        }
252
        if (!$found)
253
            throw new \UnexpectedValueException(Errors::NO_MATCHES);
254
        return $value;
255
    }
256
257
    /**
258
     * Returns the only element of a sequence, or a default value if the sequence contains no elements.
259
     * <p><b>Syntax</b>: singleOrDefault ([default])
260
     * <p>Returns the only element of a sequence, or a default value if the sequence contains no elements.
261
     * <p><b>Syntax</b>: singleOrDefault ([default [, predicate {(v, k) ==> result}]])
262
     * <p>Returns the only element of the sequence that satisfies a condition or a default value if no such element is found.
263
     * <p>If obtaining the default value is a costly operation, use {@link singleOrFallback} method to avoid overhead.
264
     * @param mixed $default A default value.
265
     * @param callable|null $predicate {(v, k) ==> result} A function to test each element for a condition. Default: true.
266
     * @throws \UnexpectedValueException If source contains more than one matching element.
267
     * @return mixed If predicate is null: default value if source is empty; otherwise, the single element of the source. If predicate is not null: default value if source is empty or if no element passes the test specified by predicate; otherwise, the single element of the source that passes the test specified by predicate.
268
     * @package YaLinqo\Pagination
269
     */
270
    public function singleOrDefault($default = null, $predicate = null)
271
    {
272
        $predicate = Utils::createLambda($predicate, 'v,k', Functions::$true);
273
274
        $found = false;
275
        $value = null;
276
        foreach ($this as $k => $v) {
277
            if ($predicate($v, $k)) {
278
                if ($found)
279
                    throw new \UnexpectedValueException(Errors::MANY_MATCHES);
280
                $found = true;
281
                $value = $v;
282
            }
283
        }
284
        return $found ? $value : $default;
285
    }
286
287
    /**
288
     * Returns the only element of a sequence, or the result of calling a fallback function if the sequence contains no elements.
289
     * <p><b>Syntax</b>: singleOrFallback ([fallback {() ==> value}])
290
     * <p>Returns the only element of a sequence, or the result of calling a fallback function if the sequence contains no elements.
291
     * <p><b>Syntax</b>: singleOrFallback ([fallback {() ==> value} [, predicate {(v, k) ==> result}]])
292
     * <p>Returns the only element of the sequence that satisfies a condition or the result of calling a fallback function if no such element is found.
293
     * <p>The fallback function is not executed if a matching element is found. Use the singleOrFallback method if obtaining the default value is a costly operation to avoid overhead. Otherwise, use {@link singleOrDefault}.
294
     * @param callable $fallback {() ==> value} A fallback function to return the default element.
295
     * @param callable|null $predicate {(v, k) ==> result} A function to test each element for a condition. Default: true.
296
     * @throws \UnexpectedValueException If source contains more than one matching element.
297
     * @return mixed If predicate is null: the result of calling a fallback function if source is empty; otherwise, the single element of the source. If predicate is not null: the result of calling a fallback function if source is empty or if no element passes the test specified by predicate; otherwise, the single element of the source that passes the test specified by predicate.
298
     * @package YaLinqo\Pagination
299
     */
300
    public function singleOrFallback($fallback, $predicate = null)
301
    {
302
        $predicate = Utils::createLambda($predicate, 'v,k', Functions::$true);
303
304
        $found = false;
305
        $value = null;
306
        foreach ($this as $k => $v) {
307
            if ($predicate($v, $k)) {
308
                if ($found)
309
                    throw new \UnexpectedValueException(Errors::MANY_MATCHES);
310
                $found = true;
311
                $value = $v;
312
            }
313
        }
314
        return $found ? $value : $fallback();
315
    }
316
317
    /**
318
     * Searches for the specified value and returns the key of the first occurrence.
319
     * <p><b>Syntax</b>: indexOf (value)
320
     * <p>To search for the zero-based index of the first occurence, call {@link toValues} method first.
321
     * @param mixed $value The value to locate in the sequence.
322
     * @return mixed The key of the first occurrence of value, if found; otherwise, false.
323
     * @package YaLinqo\Pagination
324
     */
325
    public function indexOf($value)
326
    {
327
        $array = $this->tryGetArrayCopy();
0 ignored issues
show
Bug introduced by
It seems like tryGetArrayCopy() must be provided by classes using this trait. How about adding it as abstract method to this trait?

This check looks for methods that are used by a trait but not required by it.

To illustrate, let’s look at the following code example

trait Idable {
    public function equalIds(Idable $other) {
        return $this->getId() === $other->getId();
    }
}

The trait Idable provides a method equalsId that in turn relies on the method getId(). If this method does not exist on a class mixing in this trait, the method will fail.

Adding the getId() as an abstract method to the trait will make sure it is available.

Loading history...
328
        if ($array !== null)
329
            return array_search($value, $array, true);
330
        else {
331
            foreach ($this as $k => $v) {
332
                if ($v === $value)
333
                    return $k;
334
            }
335
            return false;
336
        }
337
    }
338
339
    /**
340
     * Searches for the specified value and returns the key of the last occurrence.
341
     * <p><b>Syntax</b>: lastIndexOf (value)
342
     * <p>To search for the zero-based index of the last occurence, call {@link toValues} method first.
343
     * @param mixed $value The value to locate in the sequence.
344
     * @return mixed The key of the last occurrence of value, if found; otherwise, null.
345
     * @package YaLinqo\Pagination
346
     */
347
    public function lastIndexOf($value)
348
    {
349
        $key = null;
350
        foreach ($this as $k => $v) {
351
            if ($v === $value)
352
                $key = $k;
353
        }
354
        return $key; // not -1
355
    }
356
357
    /**
358
     * Searches for an element that matches the conditions defined by the specified predicate, and returns the key of the first occurrence.
359
     * <p><b>Syntax</b>: findIndex (predicate {(v, k) ==> result})
360
     * <p>To search for the zero-based index of the first occurence, call {@link toValues} method first.
361
     * @param callable $predicate {(v, k) ==> result} A function that defines the conditions of the element to search for.
362
     * @return mixed The key of the first occurrence of an element that matches the conditions defined by predicate, if found; otherwise, null.
363
     * @package YaLinqo\Pagination
364
     */
365
    public function findIndex($predicate)
366
    {
367
        $predicate = Utils::createLambda($predicate, 'v,k');
368
369
        foreach ($this as $k => $v) {
370
            if ($predicate($v, $k))
371
                return $k;
372
        }
373
        return null; // not -1
374
    }
375
376
    /**
377
     * Searches for an element that matches the conditions defined by the specified predicate, and returns the key of the last occurrence.
378
     * <p><b>Syntax</b>: findLastIndex (predicate {(v, k) ==> result})
379
     * <p>To search for the zero-based index of the last occurence, call {@link toValues} method first.
380
     * @param callable $predicate {(v, k) ==> result} A function that defines the conditions of the element to search for.
381
     * @return mixed The key of the last occurrence of an element that matches the conditions defined by predicate, if found; otherwise, null.
382
     * @package YaLinqo\Pagination
383
     */
384
    public function findLastIndex($predicate)
385
    {
386
        $predicate = Utils::createLambda($predicate, 'v,k');
387
388
        $key = null;
389
        foreach ($this as $k => $v) {
390
            if ($predicate($v, $k))
391
                $key = $k;
392
        }
393
        return $key; // not -1
394
    }
395
396
    /**
397
     * Bypasses a specified number of elements in a sequence and then returns the remaining elements.
398
     * <p><b>Syntax</b>: skip (count)
399
     * <p>If source contains fewer than count elements, an empty sequence is returned. If count is less than or equal to zero, all elements of source are yielded.
400
     * <p>The {@link take} and skip methods are functional complements. Given a sequence coll and an integer n, concatenating the results of coll->take(n) and coll->skip(n) yields the same sequence as coll.
401
     * @param int $count The number of elements to skip before returning the remaining elements.
402
     * @return Enumerable A sequence that contains the elements that occur after the specified index in the input sequence.
403
     * @package YaLinqo\Pagination
404
     */
405
    public function skip(int $count)
406
    {
407
        return new self(function() use ($count) {
408
            $it = $this->getIterator();
409
            $it->rewind();
410
            for ($i = 0; $i < $count && $it->valid(); ++$i)
411
                $it->next();
412
            while ($it->valid()) {
413
                yield $it->key() => $it->current();
414
                $it->next();
415
            }
416
        });
417
    }
418
419
    /**
420
     * Bypasses elements in a sequence as long as a specified condition is true and then returns the remaining elements.
421
     * <p><b>Syntax</b>: skipWhile (predicate {(v, k) ==> result})
422
     * <p>This method tests each element of source by using predicate and skips the element if the result is true. After the predicate function returns false for an element, that element and the remaining elements in source are yielded and there are no more invocations of predicate. If predicate returns true for all elements in the sequence, an empty sequence is returned.
423
     * <p>The {@link takeWhile} and skipWhile methods are functional complements. Given a sequence coll and a pure function p, concatenating the results of coll->takeWhile(p) and coll->skipWhile(p) yields the same sequence as coll.
424
     * @param callable $predicate {(v, k) ==> result} A function to test each element for a condition.
425
     * @return Enumerable A sequence that contains the elements from the input sequence starting at the first element in the linear series that does not pass the test specified by predicate.
426
     * @package YaLinqo\Pagination
427
     */
428
    public function skipWhile($predicate)
429
    {
430
        $predicate = Utils::createLambda($predicate, 'v,k');
431
432
        return new self(function() use ($predicate) {
433
            $yielding = false;
434
            foreach ($this as $k => $v) {
435
                if (!$yielding && !$predicate($v, $k))
436
                    $yielding = true;
437
                if ($yielding)
438
                    yield $k => $v;
439
            }
440
        });
441
    }
442
443
    /**
444
     * Returns a specified number of contiguous elements from the start of a sequence.
445
     * <p><b>Syntax</b>: take (count)
446
     * <p>Take enumerates source and yields elements until count elements have been yielded or source contains no more elements. If count is less than or equal to zero, source is not enumerated and an empty sequence is returned.
447
     * <p>The take and {@link skip} methods are functional complements. Given a sequence coll and an integer n, concatenating the results of coll->take(n) and coll->skip(n) yields the same sequence as coll.
448
     * @param int $count The number of elements to return.
449
     * @return Enumerable A sequence that contains the specified number of elements from the start of the input sequence.
450
     * @package YaLinqo\Pagination
451
     */
452
    public function take(int $count)
453
    {
454
        if ($count <= 0)
455
            return new self(new \EmptyIterator, false);
456
457
        return new self(function() use ($count) {
458
            foreach ($this as $k => $v) {
459
                yield $k => $v;
460
                if (--$count == 0)
461
                    break;
462
            }
463
        });
464
    }
465
466
    /**
467
     * Returns elements from a sequence as long as a specified condition is true.
468
     * <p><b>Syntax</b>: takeWhile (predicate {(v, k) ==> result})
469
     * <p>The takeWhile method tests each element of source by using predicate and yields the element if the result is true. Enumeration stops when the predicate function returns false for an element or when source contains no more elements.
470
     * <p>The takeWhile and {@link skipWhile} methods are functional complements. Given a sequence coll and a pure function p, concatenating the results of coll->takeWhile(p) and coll->skipWhile(p) yields the same sequence as coll.
471
     * @param callable $predicate {(v, k) ==> result} A function to test each element for a condition.
472
     * @return Enumerable A sequence that contains the elements from the input sequence that occur before the element at which the test no longer passes.
473
     * @package YaLinqo\Pagination
474
     */
475
    public function takeWhile($predicate)
476
    {
477
        $predicate = Utils::createLambda($predicate, 'v,k');
478
479
        return new self(function() use ($predicate) {
480
            foreach ($this as $k => $v) {
481
                if (!$predicate($v, $k))
482
                    break;
483
                yield $k => $v;
484
            }
485
        });
486
    }
487
488
    /**
489
     * Retrieve an external iterator.
490
     * @return \Iterator
491
     */
492
    public abstract function getIterator();
493
}