diff --git a/system/Helpers/Array/ArrayHelper.php b/system/Helpers/Array/ArrayHelper.php index cadac28d6c29..7d1098680ffa 100644 --- a/system/Helpers/Array/ArrayHelper.php +++ b/system/Helpers/Array/ArrayHelper.php @@ -319,4 +319,44 @@ public static function sortValuesByNatural(array &$array, $sortByIndex = null): return strnatcmp((string) $currentValue, (string) $nextValue); }); } + + /** + * Duplicate Array Check by Column + * + * @param array|string $column Unique Column + * @param array $data Array Data + */ + public static function arrayDuplicatesBy($column, array $data = []): array + { + if ($data === []) { + return []; + } + + $duplicateData = []; + $dataUnique = []; + + foreach ($data as $lineIndex => $searchData) { + if (is_array($column)) { + foreach ($column as $rawColumn) { + if (in_array($searchData[$rawColumn], $dataUnique[$rawColumn] ?? [], true)) { + $duplicateData[$lineIndex][$rawColumn] = $searchData[$rawColumn]; + } else { + $dataUnique[$rawColumn][] = $searchData[$rawColumn]; + } + } + } + + if (is_string($column)) { + if (in_array($searchData[$column], $dataUnique[$column] ?? [], true)) { + $duplicateData[$lineIndex][$column] = $searchData[$column]; + } else { + $dataUnique[$column][] = $searchData[$column]; + } + } + } + + unset($dataUnique); + + return $duplicateData; + } } diff --git a/system/Helpers/array_helper.php b/system/Helpers/array_helper.php index 837a612e4cef..e676719aa5a5 100644 --- a/system/Helpers/array_helper.php +++ b/system/Helpers/array_helper.php @@ -15,6 +15,21 @@ // CodeIgniter Array Helpers +if (! function_exists('array_duplicate_by')) { + /** + * Duplicate array check by column. + * + * @param array|string $column Unique Column + * @param array $data Array Data + * + * @return array + */ + function array_duplicate_by($column, array $data = []) + { + return ArrayHelper::arrayDuplicatesBy($column, $data); + } +} + if (! function_exists('dot_array_search')) { /** * Searches an array through dot syntax. Supports diff --git a/tests/system/Helpers/Array/ArrayHelperDuplicateCheckTest.php b/tests/system/Helpers/Array/ArrayHelperDuplicateCheckTest.php new file mode 100644 index 000000000000..014f721c3622 --- /dev/null +++ b/tests/system/Helpers/Array/ArrayHelperDuplicateCheckTest.php @@ -0,0 +1,68 @@ + + * + * For the full copyright and license information, please view + * the LICENSE file that was distributed with this source code. + */ + +namespace CodeIgniter\Helpers\Array; + +use CodeIgniter\Test\CIUnitTestCase; + +/** + * @group Others + * + * @internal + */ +final class ArrayHelperDuplicateCheckTest extends CIUnitTestCase +{ + private array $array = [ + [ + 'name' => 'Fred Flinstone', + 'age' => 20, + ], + [ + 'name' => 'Brad Pierce', + 'age' => 30, + ], + [ + 'name' => 'Fred Flinstone', + 'age' => 70, + ], + [ + 'name' => 'Michelle Stone', + 'age' => 30, + ], + [ + 'name' => 'Michael Bram', + 'age' => 40, + ], + ]; + + public function testSingleColumn(): void + { + $this->assertSame([ + 2 => [ + 'name' => 'Fred Flinstone', + ], + ], ArrayHelper::arrayDuplicatesBy('name', $this->array)); + } + + public function testMultipleColumn(): void + { + $this->assertSame([ + 2 => [ + 'name' => 'Fred Flinstone', + ], + 3 => [ + 'age' => 30, + ], + ], ArrayHelper::arrayDuplicatesBy(['name', 'age'], $this->array)); + } +} diff --git a/tests/system/Helpers/ArrayHelperTest.php b/tests/system/Helpers/ArrayHelperTest.php index c7beb0e405b4..31a3b76f4878 100644 --- a/tests/system/Helpers/ArrayHelperTest.php +++ b/tests/system/Helpers/ArrayHelperTest.php @@ -1287,4 +1287,79 @@ public static function provideArrayGroupByExcludeEmpty(): iterable ], ]; } + + /** + * @dataProvider provideArrayDuplicate + * + * @param mixed $column + */ + public function testArrayDuplicate($column, array $data, array $expected): void + { + $this->assertSame($expected, array_duplicate_by($column, $data)); + } + + public static function provideArrayDuplicate(): iterable + { + yield 'single and multiple' => [ + 'name', // Single + [ + [ + 'name' => 'Fred Flinstone', + 'age' => 20, + ], + [ + 'name' => 'Brad Pierce', + 'age' => 30, + ], + [ + 'name' => 'Fred Flinstone', + 'age' => 70, + ], + [ + 'name' => 'Michelle Stone', + 'age' => 30, + ], + [ + 'name' => 'Michael Bram', + 'age' => 40, + ], + ], + [ + 2 => [ + 'name' => 'Fred Flinstone', + ], + ], + ['name', 'age'], // Multiple + [ + [ + 'name' => 'Fred Flinstone', + 'age' => 20, + ], + [ + 'name' => 'Brad Pierce', + 'age' => 30, + ], + [ + 'name' => 'Fred Flinstone', + 'age' => 70, + ], + [ + 'name' => 'Michelle Stone', + 'age' => 30, + ], + [ + 'name' => 'Michael Bram', + 'age' => 40, + ], + ], + [ + 2 => [ + 'name' => 'Fred Flinstone', + ], + 3 => [ + 'age' => 30, + ], + ], + ]; + } }