From 17532793e68a87e7ad31ad62e4d0b0a603f8ddd0 Mon Sep 17 00:00:00 2001 From: chadicus Date: Tue, 22 Sep 2020 13:41:06 -0400 Subject: [PATCH 1/2] Add DuplicateValueException --- src/Exceptions/DuplicateValuesException.php | 22 ++++++++++++++++ .../DuplicateValuesExceptionTest.php | 26 +++++++++++++++++++ 2 files changed, 48 insertions(+) create mode 100644 src/Exceptions/DuplicateValuesException.php create mode 100644 tests/Exceptions/DuplicateValuesExceptionTest.php diff --git a/src/Exceptions/DuplicateValuesException.php b/src/Exceptions/DuplicateValuesException.php new file mode 100644 index 0000000..20b293b --- /dev/null +++ b/src/Exceptions/DuplicateValuesException.php @@ -0,0 +1,22 @@ +assertSame( + sprintf(DuplicateValuesException::ERROR_FORMAT, var_export($duplicates, true)), + $exception->getMessage() + ); + } +} From 45f124eb4e2acb883fc4a6e2bdbed8d5e8288c01 Mon Sep 17 00:00:00 2001 From: chadicus Date: Tue, 22 Sep 2020 13:46:26 -0400 Subject: [PATCH 2/2] Add Arrays::unique --- README.md | 9 +++++++ src/Arrays.php | 62 ++++++++++++++++++++++++++++++++++++++++++++ tests/ArraysTest.php | 27 +++++++++++++++++++ 3 files changed, 98 insertions(+) diff --git a/README.md b/README.md index 26a4b06..cc70666 100644 --- a/README.md +++ b/README.md @@ -84,6 +84,15 @@ $value = \TraderInteractive\Filter\Arrays::pad([1, 2], 5, 0, \TraderInteractive\ assert($value === [0, 0, 0, 1, 2]); ``` +#### Arrays::unique + +This filter removes any duplicate values in the given array. Optionally throwing an exception if duplicate values are found. + +```php +$value = \TraderInteractive\Filter\Arrays::unique(['foo', 'bar', 'foo']); +assert($value === ['foo', 'bar']); +``` + ## Project Build With a checkout of the code get [Composer](http://getcomposer.org) in your PATH and run: diff --git a/src/Arrays.php b/src/Arrays.php index 583c93a..ee27b33 100644 --- a/src/Arrays.php +++ b/src/Arrays.php @@ -4,6 +4,7 @@ use InvalidArgumentException; use TraderInteractive\Exceptions\FilterException; +use TraderInteractive\Filter\Exceptions\DuplicateValuesException; /** * A collection of filters for arrays. @@ -20,6 +21,26 @@ final class Arrays */ const ARRAY_PAD_FRONT = 2; + /** + * @var int + */ + const ARRAY_UNIQUE_SORT_REGULAR = \SORT_REGULAR; + + /** + * @var int + */ + const ARRAY_UNIQUE_SORT_NUMERIC = \SORT_NUMERIC; + + /** + * @var int + */ + const ARRAY_UNIQUE_SORT_STRING = \SORT_STRING; + + /** + * @var int + */ + const ARRAY_UNIQUE_SORT_LOCALE_STRING = \SORT_LOCALE_STRING; + /** * Filter an array by throwing if not an array or count not in the min/max range. * @@ -189,4 +210,45 @@ public static function pad(array $input, int $size, $padValue = null, int $padTy return $input; } + + /** + * Removes duplicate values from an array. + * + * @param array $input The array to be filtered. + * @param int $sortFlags Optional parameter used to modify the sorting behavior. + * @param bool $strict If set to TRUE the filter will throw exception if the $input array contains duplicates. + * + * @return array + * + * @throws FilterException Thrown if the array contains duplicates and $strict is true. + */ + public static function unique( + array $input, + int $sortFlags = self::ARRAY_UNIQUE_SORT_REGULAR, + bool $strict = false + ) : array { + $unique = array_unique($input, $sortFlags); + if ($unique !== $input && $strict === true) { + $duplicateValues = self::findDuplicates($input); + throw new DuplicateValuesException($duplicateValues); + } + + return $unique; + } + + private static function findDuplicates(array $input) : array + { + $temp = []; + $duplicates = []; + foreach ($input as $key => $value) { + if (!in_array($value, $temp, true)) { + $temp[] = $value; + continue; + } + + $duplicates[$key] = $value; + } + + return $duplicates; + } } diff --git a/tests/ArraysTest.php b/tests/ArraysTest.php index 0c32a0d..e499faa 100644 --- a/tests/ArraysTest.php +++ b/tests/ArraysTest.php @@ -5,9 +5,11 @@ use InvalidArgumentException; use PHPUnit\Framework\TestCase; use TraderInteractive\Exceptions\FilterException; +use TraderInteractive\Filter\Exceptions\DuplicateValuesException; /** * @coversDefaultClass \TraderInteractive\Filter\Arrays + * @covers :: */ final class ArraysTest extends TestCase { @@ -240,4 +242,29 @@ public function padInvalidPadType() $this->expectExceptionMessage('Invalid $padType value provided'); Arrays::pad(['a', 'b', 'c'], 5, null, 0); } + + /** + * @test + * @covers ::unique + */ + public function unique() + { + $input = ['foo', 'bar', 'foo']; + $filteredValue = Arrays::unique($input); + $this->assertSame(['foo', 'bar'], $filteredValue); + } + + /** + * @test + * @covers ::unique + */ + public function uniqueStrict() + { + $input = ['foo', 'bar', 'foo']; + $expectedDuplicates = ['2' => 'foo']; + $expectedException = new DuplicateValuesException($expectedDuplicates); + $this->expectException(DuplicateValuesException::class); + $this->expectExceptionMessage($expectedException->getMessage()); + Arrays::unique($input, Arrays::ARRAY_UNIQUE_SORT_STRING, true); + } }