Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Adding key_sort functionality #234

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@
"src/Functional/InvokeIf.php",
"src/Functional/InvokeLast.php",
"src/Functional/Invoker.php",
"src/Functional/KeySort.php",
"src/Functional/Last.php",
"src/Functional/LastIndexOf.php",
"src/Functional/LessThan.php",
Expand Down
5 changes: 5 additions & 0 deletions src/Functional/Functional.php
Original file line number Diff line number Diff line change
Expand Up @@ -223,6 +223,11 @@ final class Functional
*/
const invoker = '\Functional\invoker';

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

/**
* @see \Functional\last
*/
Expand Down
44 changes: 44 additions & 0 deletions src/Functional/KeySort.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
<?php

/**
* @package Functional-php
* @author Adrian Panicek <[email protected]>
* @license https://opensource.org/licenses/MIT MIT
* @link https://github.com/adrianpanicek/functional-php
*/

namespace Functional;

use Traversable;
use Functional\Exceptions\InvalidArgumentException;

/**
* Sort collection by array keys
*
* @param Traversable|array $collection
* @param callable|null $callback
*
* @return array
*/
function key_sort($collection, callable $callback = null)
{
InvalidArgumentException::assertCollection($collection, __FUNCTION__, 1);

if ($collection instanceof Traversable) {
$array = \iterator_to_array($collection);
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A Traversable is not always an iterator.

} else {
$array = $collection;
}

if ($callback === null) {
\ksort($array);

return $array;
}

\uksort($array, static function ($a, $b) use ($callback, $array) {
return $callback($a, $b, $array);
});

return $array;
}
94 changes: 94 additions & 0 deletions tests/Functional/KeySortTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
<?php

/**
* @package Functional-php
* @author Adrian Panicek <[email protected]>
* @license https://opensource.org/licenses/MIT MIT
* @link https://github.com/adrianpanicek/functional-php
*/

namespace Functional\Tests;

use ArrayIterator;
use Functional as F;
use Functional\Exceptions\InvalidArgumentException;

use function Functional\key_sort;

class KeySortTest extends AbstractTestCase
{
public function setUp()
{
parent::setUp();
$this->list = ['cat', 'bear', 'aardvark'];
$this->listIterator = new ArrayIterator($this->list);
$this->hash = ['c' => 'cat', 'b' => 'bear', 'a' => 'aardvark'];
$this->hashIterator = new ArrayIterator($this->hash);
$this->ksortCallback = function ($left, $right, $collection) {
InvalidArgumentException::assertCollection($collection, __FUNCTION__, 3);
return strcmp($left, $right);
};
}

public function testWithoutCallback()
{
$this->assertSame(['cat', 'bear', 'aardvark'], F\key_sort($this->list));
$this->assertSame(['cat', 'bear', 'aardvark'], F\key_sort($this->listIterator));
$this->assertSame(['a' => 'aardvark', 'b' => 'bear', 'c' => 'cat'], F\key_sort($this->hash));
$this->assertSame(['a' => 'aardvark', 'b' => 'bear', 'c' => 'cat'], F\key_sort($this->hashIterator));
}

public function testWithCallback()
{
$this->assertSame(['cat', 'bear', 'aardvark'], F\key_sort($this->list, $this->ksortCallback));
$this->assertSame(['cat', 'bear', 'aardvark'], F\key_sort($this->listIterator, $this->ksortCallback));
$this->assertSame(['a' => 'aardvark', 'b' => 'bear', 'c' => 'cat'], F\key_sort($this->hash, $this->ksortCallback));
$this->assertSame(['a' => 'aardvark', 'b' => 'bear', 'c' => 'cat'], F\key_sort($this->hashIterator, $this->ksortCallback));
}

public function testImmutability()
{
F\key_sort($this->hash);
$this->assertSame(['c' => 'cat', 'b' => 'bear', 'a' => 'aardvark'], $this->hash);
}

public function testPassNonCallable()
{
$this->expectArgumentError("Argument 2 passed to Functional\key_sort() must be callable or null");
F\key_sort($this->list, 'undefinedFunction');
}

public function testPassNoCollection()
{
$this->expectArgumentError('key_sort() expects parameter 1 to be array or instance of Traversable');
F\key_sort('invalidCollection', 'strlen');
}

public function testExceptionIsThrownInArray()
{
$this->expectException('DomainException');
$this->expectExceptionMessage('Callback exception');
F\key_sort($this->list, [$this, 'exception']);
}

public function testExceptionIsThrownInHash()
{
$this->expectException('DomainException');
$this->expectExceptionMessage('Callback exception');
F\key_sort($this->hash, [$this, 'exception']);
}

public function testExceptionIsThrownInIterator()
{
$this->expectException('DomainException');
$this->expectExceptionMessage('Callback exception');
F\key_sort($this->listIterator, [$this, 'exception']);
}

public function testExceptionIsThrownInHashIterator()
{
$this->expectException('DomainException');
$this->expectExceptionMessage('Callback exception');
F\key_sort($this->hashIterator, [$this, 'exception']);
}
}