Skip to content

Commit 79639d4

Browse files
phananlstrojny
authored andcommitted
Add take_left() and take_right() (lstrojny#192)
1 parent c45ce47 commit 79639d4

File tree

7 files changed

+255
-2
lines changed

7 files changed

+255
-2
lines changed

composer.json

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,8 @@
105105
"src/Functional/Tap.php",
106106
"src/Functional/Tail.php",
107107
"src/Functional/TailRecursion.php",
108+
"src/Functional/TakeLeft.php",
109+
"src/Functional/TakeRight.php",
108110
"src/Functional/True.php",
109111
"src/Functional/Truthy.php",
110112
"src/Functional/Unique.php",

docs/functional-php.md

Lines changed: 27 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@
1717
- [truthy() & falsy()](#truthy--falsy)
1818
- [contains()](#contains)
1919
- [sort()](#sort)
20-
- [Other:](#other)
20+
- [Other](#other)
2121
- [Partial application](#partial-application)
2222
- [Introduction](#introduction)
2323
- [partial_left() & partial_right()](#partial_left--partial_right)
@@ -37,6 +37,8 @@
3737
- [last_index_of()](#last_index_of)
3838
- [indexes_of()](#indexes_of)
3939
- [select_keys()](#select_keys)
40+
- [take_left()](#take_left)
41+
- [take_right()](#take_right)
4042
- [Function functions](#function-functions)
4143
- [retry()](#retry)
4244
- [poll()](#poll)
@@ -267,7 +269,7 @@ sort($collection, function($user1, $user2) {
267269
```
268270

269271

270-
## Other:
272+
## Other
271273

272274
`void Functional\each(array|Traversable $collection, callable $callback)`
273275
Applies a callback to each element
@@ -627,6 +629,29 @@ use function Functional\select_keys;
627629
$array = select_keys(['foo' => 1, 'bar' => 2', 'baz' => 3], ['foo', 'baz']);
628630
```
629631

632+
## take_left()
633+
634+
Creates a slice of `$collection` with `$count` elements taken from the beginning. If the collection has less than `$count` elements, the whole collection will be returned as an array.
635+
636+
``array Functional\take_left(Traversable|array $collection, int $count)``
637+
638+
```php
639+
Functional\take_left([1, 2, 3], 2); // [1, 2]
640+
```
641+
642+
## take_right()
643+
644+
Creates a slice of `$collection` with `$count` elements taken from the end. If the collection has less than `$count` elements, the whole collection will be returned as an array.
645+
646+
This function will reorder and reset the integer array indices by default. This behaviour can be changed by setting `$preserveKeys` to `true`. String keys are always preserved, regardless of this parameter.
647+
648+
``array Functional\take_right(Traversable|array $collection, int $count, bool $preserveKeys = false)``
649+
650+
```php
651+
Functional\take_right([1, 2, 3], 2); // [2, 3]
652+
Functional\take_right(['a', 'b', 'c'], 2, true); // [1 => 'b', 2 => 'c']
653+
```
654+
630655
# Function functions
631656

632657
Function functions take a function or functions and return a new, modified version of the function.

src/Functional/Functional.php

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -409,6 +409,16 @@ final class Functional
409409
*/
410410
const tail_recursion = '\Functional\tail_recursion';
411411

412+
/**
413+
* @see \Functional\take_left
414+
*/
415+
const take = '\Functional\take_left';
416+
417+
/**
418+
* @see \Functional\take_right
419+
*/
420+
const take_right = '\Functional\take_right';
421+
412422
/**
413423
* @see \Functional\tap
414424
*/

src/Functional/TakeLeft.php

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
<?php
2+
/**
3+
* Copyright (C) 2011-2017 by Lars Strojny <lstrojny@php.net>
4+
*
5+
* Permission is hereby granted, free of charge, to any person obtaining a copy
6+
* of this software and associated documentation files (the "Software"), to deal
7+
* in the Software without restriction, including without limitation the rights
8+
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9+
* copies of the Software, and to permit persons to whom the Software is
10+
* furnished to do so, subject to the following conditions:
11+
*
12+
* The above copyright notice and this permission notice shall be included in
13+
* all copies or substantial portions of the Software.
14+
*
15+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16+
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17+
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18+
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19+
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20+
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21+
* THE SOFTWARE.
22+
*/
23+
namespace Functional;
24+
25+
use Functional\Exceptions\InvalidArgumentException;
26+
use Traversable;
27+
28+
/**
29+
* Creates a slice of $collection with $count elements taken from the beginning. If the collection has less than $count
30+
* elements, the whole collection will be returned as an array.
31+
*
32+
* @param Traversable|array $collection
33+
* @param int $count
34+
*
35+
* @return array
36+
*/
37+
function take_left($collection, $count)
38+
{
39+
InvalidArgumentException::assertCollection($collection, __FUNCTION__, 1);
40+
InvalidArgumentException::assertPositiveInteger($count, __FUNCTION__, 2);
41+
42+
return \array_slice(
43+
\is_array($collection) ? $collection : \iterator_to_array($collection),
44+
0,
45+
$count
46+
);
47+
}

src/Functional/TakeRight.php

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
<?php
2+
/**
3+
* Copyright (C) 2011-2017 by Lars Strojny <lstrojny@php.net>
4+
*
5+
* Permission is hereby granted, free of charge, to any person obtaining a copy
6+
* of this software and associated documentation files (the "Software"), to deal
7+
* in the Software without restriction, including without limitation the rights
8+
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9+
* copies of the Software, and to permit persons to whom the Software is
10+
* furnished to do so, subject to the following conditions:
11+
*
12+
* The above copyright notice and this permission notice shall be included in
13+
* all copies or substantial portions of the Software.
14+
*
15+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16+
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17+
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18+
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19+
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20+
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21+
* THE SOFTWARE.
22+
*/
23+
namespace Functional;
24+
25+
use Functional\Exceptions\InvalidArgumentException;
26+
use Traversable;
27+
28+
/**
29+
* Creates a slice of $collection with $count elements taken from the end. If the collection has less than $count
30+
* elements, the whole collection will be returned as an array.
31+
* This function will reorder and reset the integer array indices by default. This behaviour can be changed by setting
32+
* preserveKeys to TRUE. String keys are always preserved, regardless of this parameter.
33+
*
34+
* @param Traversable|array $collection
35+
* @param int $count
36+
* @param bool $preserveKeys
37+
*
38+
* @return array
39+
*/
40+
function take_right($collection, $count, $preserveKeys = false)
41+
{
42+
InvalidArgumentException::assertCollection($collection, __FUNCTION__, 1);
43+
InvalidArgumentException::assertPositiveInteger($count, __FUNCTION__, 2);
44+
45+
return \array_slice(
46+
\is_array($collection) ? $collection : \iterator_to_array($collection),
47+
0 - $count,
48+
$count,
49+
$preserveKeys
50+
);
51+
}

tests/Functional/TakeLeftTest.php

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
<?php
2+
/**
3+
* Copyright (C) 2011-2017 by Lars Strojny <lstrojny@php.net>
4+
*
5+
* Permission is hereby granted, free of charge, to any person obtaining a copy
6+
* of this software and associated documentation files (the "Software"), to deal
7+
* in the Software without restriction, including without limitation the rights
8+
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9+
* copies of the Software, and to permit persons to whom the Software is
10+
* furnished to do so, subject to the following conditions:
11+
*
12+
* The above copyright notice and this permission notice shall be included in
13+
* all copies or substantial portions of the Software.
14+
*
15+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16+
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17+
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18+
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19+
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20+
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21+
* THE SOFTWARE.
22+
*/
23+
namespace Functional\Tests;
24+
25+
use ArrayIterator;
26+
use function Functional\each;
27+
use function Functional\take_left;
28+
29+
class TakeLeftTest extends AbstractTestCase
30+
{
31+
public function setUp()
32+
{
33+
parent::setUp();
34+
35+
$this->list = ['foo', 'bar', 'baz', 'qux'];
36+
$this->listIterator = new ArrayIterator($this->list);
37+
}
38+
39+
public function test()
40+
{
41+
each([$this->list, $this->listIterator], function ($list) {
42+
$this->assertSame(['foo'], take_left($list, 1));
43+
$this->assertSame(['foo', 'bar'], take_left($list, 2));
44+
$this->assertSame(['foo', 'bar', 'baz', 'qux'], take_left($list, 10));
45+
$this->assertSame([], take_left($list, 0));
46+
47+
$this->expectExceptionMessage(
48+
'Functional\take_left() expects parameter 2 to be positive integer, negative integer given'
49+
);
50+
take_left($list, -1);
51+
});
52+
}
53+
}

tests/Functional/TakeRightTest.php

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
<?php
2+
/**
3+
* Copyright (C) 2011-2017 by Lars Strojny <lstrojny@php.net>
4+
*
5+
* Permission is hereby granted, free of charge, to any person obtaining a copy
6+
* of this software and associated documentation files (the "Software"), to deal
7+
* in the Software without restriction, including without limitation the rights
8+
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9+
* copies of the Software, and to permit persons to whom the Software is
10+
* furnished to do so, subject to the following conditions:
11+
*
12+
* The above copyright notice and this permission notice shall be included in
13+
* all copies or substantial portions of the Software.
14+
*
15+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16+
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17+
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18+
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19+
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20+
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21+
* THE SOFTWARE.
22+
*/
23+
namespace Functional\Tests;
24+
25+
use ArrayIterator;
26+
use function Functional\each;
27+
use function Functional\take_right;
28+
29+
class TakeRightTest extends AbstractTestCase
30+
{
31+
public function setUp()
32+
{
33+
parent::setUp();
34+
35+
$this->list = ['foo', 'bar', 'baz', 'qux'];
36+
$this->listIterator = new ArrayIterator($this->list);
37+
}
38+
39+
public function test()
40+
{
41+
each([$this->list, $this->listIterator], function ($list) {
42+
$this->assertSame(['qux'], take_right($list, 1));
43+
$this->assertSame(['baz', 'qux'], take_right($list, 2));
44+
$this->assertSame(['foo', 'bar', 'baz', 'qux'], take_right($list, 10));
45+
$this->assertSame([], take_right($list, 0));
46+
47+
$this->expectExceptionMessage(
48+
'Functional\take_right() expects parameter 2 to be positive integer, negative integer given'
49+
);
50+
take_right($list, -1);
51+
});
52+
}
53+
54+
public function testPreserveKeys()
55+
{
56+
each([$this->list, $this->listIterator], function ($list) {
57+
$this->assertSame([3 => 'qux'], take_right($list, 1, true));
58+
$this->assertSame([2 => 'baz', 3 => 'qux'], take_right($list, 2, true));
59+
60+
// "special" cases should behave the same as with $preserveKeys = false
61+
$this->assertSame(['foo', 'bar', 'baz', 'qux'], take_right($list, 10, true));
62+
$this->assertSame([], take_right($list, 0, true));
63+
});
64+
}
65+
}

0 commit comments

Comments
 (0)