Skip to content

Commit

Permalink
Add take_left() and take_right() (#192)
Browse files Browse the repository at this point in the history
  • Loading branch information
phanan authored and lstrojny committed Sep 26, 2019
1 parent c45ce47 commit 79639d4
Show file tree
Hide file tree
Showing 7 changed files with 255 additions and 2 deletions.
2 changes: 2 additions & 0 deletions composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,8 @@
"src/Functional/Tap.php",
"src/Functional/Tail.php",
"src/Functional/TailRecursion.php",
"src/Functional/TakeLeft.php",
"src/Functional/TakeRight.php",
"src/Functional/True.php",
"src/Functional/Truthy.php",
"src/Functional/Unique.php",
Expand Down
29 changes: 27 additions & 2 deletions docs/functional-php.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
- [truthy() & falsy()](#truthy--falsy)
- [contains()](#contains)
- [sort()](#sort)
- [Other:](#other)
- [Other](#other)
- [Partial application](#partial-application)
- [Introduction](#introduction)
- [partial_left() & partial_right()](#partial_left--partial_right)
Expand All @@ -37,6 +37,8 @@
- [last_index_of()](#last_index_of)
- [indexes_of()](#indexes_of)
- [select_keys()](#select_keys)
- [take_left()](#take_left)
- [take_right()](#take_right)
- [Function functions](#function-functions)
- [retry()](#retry)
- [poll()](#poll)
Expand Down Expand Up @@ -267,7 +269,7 @@ sort($collection, function($user1, $user2) {
```


## Other:
## Other

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

## take_left()

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.

``array Functional\take_left(Traversable|array $collection, int $count)``

```php
Functional\take_left([1, 2, 3], 2); // [1, 2]
```

## take_right()

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.

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.

``array Functional\take_right(Traversable|array $collection, int $count, bool $preserveKeys = false)``

```php
Functional\take_right([1, 2, 3], 2); // [2, 3]
Functional\take_right(['a', 'b', 'c'], 2, true); // [1 => 'b', 2 => 'c']
```

# Function functions

Function functions take a function or functions and return a new, modified version of the function.
Expand Down
10 changes: 10 additions & 0 deletions src/Functional/Functional.php
Original file line number Diff line number Diff line change
Expand Up @@ -409,6 +409,16 @@ final class Functional
*/
const tail_recursion = '\Functional\tail_recursion';

/**
* @see \Functional\take_left
*/
const take = '\Functional\take_left';

/**
* @see \Functional\take_right
*/
const take_right = '\Functional\take_right';

/**
* @see \Functional\tap
*/
Expand Down
47 changes: 47 additions & 0 deletions src/Functional/TakeLeft.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
<?php
/**
* Copyright (C) 2011-2017 by Lars Strojny <[email protected]>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
namespace Functional;

use Functional\Exceptions\InvalidArgumentException;
use Traversable;

/**
* 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.
*
* @param Traversable|array $collection
* @param int $count
*
* @return array
*/
function take_left($collection, $count)
{
InvalidArgumentException::assertCollection($collection, __FUNCTION__, 1);
InvalidArgumentException::assertPositiveInteger($count, __FUNCTION__, 2);

return \array_slice(
\is_array($collection) ? $collection : \iterator_to_array($collection),
0,
$count
);
}
51 changes: 51 additions & 0 deletions src/Functional/TakeRight.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
<?php
/**
* Copyright (C) 2011-2017 by Lars Strojny <[email protected]>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
namespace Functional;

use Functional\Exceptions\InvalidArgumentException;
use Traversable;

/**
* 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.
* 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.
*
* @param Traversable|array $collection
* @param int $count
* @param bool $preserveKeys
*
* @return array
*/
function take_right($collection, $count, $preserveKeys = false)
{
InvalidArgumentException::assertCollection($collection, __FUNCTION__, 1);
InvalidArgumentException::assertPositiveInteger($count, __FUNCTION__, 2);

return \array_slice(
\is_array($collection) ? $collection : \iterator_to_array($collection),
0 - $count,
$count,
$preserveKeys
);
}
53 changes: 53 additions & 0 deletions tests/Functional/TakeLeftTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
<?php
/**
* Copyright (C) 2011-2017 by Lars Strojny <[email protected]>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
namespace Functional\Tests;

use ArrayIterator;
use function Functional\each;
use function Functional\take_left;

class TakeLeftTest extends AbstractTestCase
{
public function setUp()
{
parent::setUp();

$this->list = ['foo', 'bar', 'baz', 'qux'];
$this->listIterator = new ArrayIterator($this->list);
}

public function test()
{
each([$this->list, $this->listIterator], function ($list) {
$this->assertSame(['foo'], take_left($list, 1));
$this->assertSame(['foo', 'bar'], take_left($list, 2));
$this->assertSame(['foo', 'bar', 'baz', 'qux'], take_left($list, 10));
$this->assertSame([], take_left($list, 0));

$this->expectExceptionMessage(
'Functional\take_left() expects parameter 2 to be positive integer, negative integer given'
);
take_left($list, -1);
});
}
}
65 changes: 65 additions & 0 deletions tests/Functional/TakeRightTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
<?php
/**
* Copyright (C) 2011-2017 by Lars Strojny <[email protected]>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
namespace Functional\Tests;

use ArrayIterator;
use function Functional\each;
use function Functional\take_right;

class TakeRightTest extends AbstractTestCase
{
public function setUp()
{
parent::setUp();

$this->list = ['foo', 'bar', 'baz', 'qux'];
$this->listIterator = new ArrayIterator($this->list);
}

public function test()
{
each([$this->list, $this->listIterator], function ($list) {
$this->assertSame(['qux'], take_right($list, 1));
$this->assertSame(['baz', 'qux'], take_right($list, 2));
$this->assertSame(['foo', 'bar', 'baz', 'qux'], take_right($list, 10));
$this->assertSame([], take_right($list, 0));

$this->expectExceptionMessage(
'Functional\take_right() expects parameter 2 to be positive integer, negative integer given'
);
take_right($list, -1);
});
}

public function testPreserveKeys()
{
each([$this->list, $this->listIterator], function ($list) {
$this->assertSame([3 => 'qux'], take_right($list, 1, true));
$this->assertSame([2 => 'baz', 3 => 'qux'], take_right($list, 2, true));

// "special" cases should behave the same as with $preserveKeys = false
$this->assertSame(['foo', 'bar', 'baz', 'qux'], take_right($list, 10, true));
$this->assertSame([], take_right($list, 0, true));
});
}
}

0 comments on commit 79639d4

Please sign in to comment.