Skip to content

Commit

Permalink
Merge pull request #7 from chadicus/fea/unique
Browse files Browse the repository at this point in the history
Add Arrays::unique()
  • Loading branch information
chadicus authored Sep 22, 2020
2 parents da4b4ab + 45f124e commit f705886
Show file tree
Hide file tree
Showing 5 changed files with 146 additions and 0 deletions.
9 changes: 9 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand Down
62 changes: 62 additions & 0 deletions src/Arrays.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

use InvalidArgumentException;
use TraderInteractive\Exceptions\FilterException;
use TraderInteractive\Filter\Exceptions\DuplicateValuesException;

/**
* A collection of filters for arrays.
Expand All @@ -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.
*
Expand Down Expand Up @@ -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;
}
}
22 changes: 22 additions & 0 deletions src/Exceptions/DuplicateValuesException.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
<?php

namespace TraderInteractive\Filter\Exceptions;

use TraderInteractive\Exceptions\FilterException;

class DuplicateValuesException extends FilterException
{
/**
* @var string
*/
const ERROR_FORMAT = "Array contains the following duplicate values: %s";

/**
* @param array $duplicateValues The duplicate values found in the array.
*/
public function __construct(array $duplicateValues)
{
$message = sprintf(self::ERROR_FORMAT, var_export($duplicateValues, true));
parent::__construct($message);
}
}
27 changes: 27 additions & 0 deletions tests/ArraysTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,11 @@
use InvalidArgumentException;
use PHPUnit\Framework\TestCase;
use TraderInteractive\Exceptions\FilterException;
use TraderInteractive\Filter\Exceptions\DuplicateValuesException;

/**
* @coversDefaultClass \TraderInteractive\Filter\Arrays
* @covers ::<private>
*/
final class ArraysTest extends TestCase
{
Expand Down Expand Up @@ -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);
}
}
26 changes: 26 additions & 0 deletions tests/Exceptions/DuplicateValuesExceptionTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
<?php

namespace Exceptions;

use PHPUnit\Framework\TestCase;
use TraderInteractive\Filter\Exceptions\DuplicateValuesException;

/**
* @coversDefaultClass \TraderInteractive\Filter\Exceptions\DuplicateValuesException
*/
final class DuplicateValuesExceptionTest extends TestCase
{
/**
* @test
* @covers ::__construct
*/
public function basicUsage()
{
$duplicates = ['foo', 'bar'];
$exception = new DuplicateValuesException($duplicates);
$this->assertSame(
sprintf(DuplicateValuesException::ERROR_FORMAT, var_export($duplicates, true)),
$exception->getMessage()
);
}
}

0 comments on commit f705886

Please sign in to comment.