diff --git a/README.md b/README.md index a886298..fe3557f 100644 --- a/README.md +++ b/README.md @@ -19,8 +19,9 @@ Features - [x] Verify at most times: [`once()`](#1-atmostonce), [`twice()`](#2-atmosttwice), [`times()`](#3-atmosttimes) - [x] Verify exact times: [`once()`](#1-onlyonce), [`twice()`](#2-onlytwice), [`times()`](#3-onlytimes) - [x] Verify in interval range: [`isInclusiveOf()`](#1-intervalisinclusiveof), [`isExclusiveOf()`](#2-intervalisexclusiveof) +- [x] Verify all or none match: [`match()`](#1-allmatch), [`none()`](#2-allnone) - [x] Search data: [`first()`](#1-finderfirst), [`last()`](#2-finderlast), [`rows()`](#3-finderrows), [`partition()`](#4-finderpartition) -- [x] Collect data with [filter and transform](#f-collector) +- [x] Collect data with [filter and transform](#g-collector) Installation ------------ @@ -348,7 +349,70 @@ var_dump(Interval::isExclusiveOf($orders, $filter, 3, 5)) // false var_dump(Interval::isExclusiveOf($orders, $filter, 2, 5)) // true ``` -**E. Finder** +**E. All** +--------------- + +#### 1. `All::match()` + +It verify that all items match the filter and data is non-empty. + +```php +use ArrayLookup\All; + +$data = [1, 2, 3]; +$filter = static fn($datum): bool => $datum > 0; + +var_dump(All::match($data, $filter)) // true + +$data = [1, 0, 3]; +$filter = static fn($datum): bool => $datum > 0; + +var_dump(All::match($data, $filter)) // false + +$data = []; +$filter = static fn($datum): bool => $datum !== null; + +var_dump(All::match($data, $filter)) // false + +// WITH key array included, pass $key variable as 2nd arg on filter to be used in filter + +$data = ['abc', 'def']; +$filter = static fn($datum, $key): bool => $datum !== '' && $key >= 0; + +var_dump(All::match($data, $filter)) // true +``` + +#### 2. `All::none()` + +It verify that no items match the filter (empty data returns true). + +```php +use ArrayLookup\All; + +$data = [1, 2, 3]; +$filter = static fn($datum): bool => $datum === 4; + +var_dump(All::none($data, $filter)) // true + +$data = [1, 2, 3]; +$filter = static fn($datum): bool => $datum === 2; + +var_dump(All::none($data, $filter)) // false + +$data = []; +$filter = static fn($datum): bool => $datum !== null; + +var_dump(All::none($data, $filter)) // true + +// WITH key array included, pass $key variable as 2nd arg on filter to be used in filter + +$data = ['abc', 'def']; +$filter = static fn($datum, $key): bool => $key === 0 && $datum === 'abc'; + +var_dump(All::none($data, $filter)) // false +``` + +**F. Finder** --------------- #### 1. `Finder::first()` @@ -519,7 +583,7 @@ var_dump($even); // [0 => 10, 2 => 30] var_dump($odd); // [1 => 20, 3 => 40] ``` -**F. Collector** +**G. Collector** --------------- It collect filtered data, with new transformed each data found: diff --git a/src/All.php b/src/All.php new file mode 100644 index 0000000..4b22979 --- /dev/null +++ b/src/All.php @@ -0,0 +1,50 @@ +|Traversable $data + * @param callable(mixed $datum, int|string|null $key): bool $filter + */ + public static function match(iterable $data, callable $filter): bool + { + Filter::boolean($filter); + + $isNonEmpty = false; + + foreach ($data as $key => $datum) { + $isNonEmpty = true; + + if (! $filter($datum, $key)) { + return false; + } + } + + // when empty data is given, then nothing is match + return $isNonEmpty; + } + + /** + * @param array|Traversable $data + * @param callable(mixed $datum, int|string|null $key): bool $filter + */ + public static function none(iterable $data, callable $filter): bool + { + Filter::boolean($filter); + + foreach ($data as $key => $datum) { + if ($filter($datum, $key)) { + return false; + } + } + + return true; + } +} diff --git a/tests/AllTest.php b/tests/AllTest.php new file mode 100644 index 0000000..078d4a0 --- /dev/null +++ b/tests/AllTest.php @@ -0,0 +1,91 @@ +assertSame( + $expected, + All::match($data, $filter) + ); + } + + /** + * @return Iterator + */ + public static function matchDataProvider(): Iterator + { + yield [ + [1, 2, 3], + static fn($datum): bool => $datum > 0, + true, + ]; + yield [ + [1, 0, 3], + static fn($datum): bool => $datum > 0, + false, + ]; + yield [ + ['abc', 'def'], + static fn(string $datum, int $key): bool => $datum !== '' && $key >= 0, + true, + ]; + yield [ + [], + static fn($datum): bool => $datum !== null, + false, + ]; + } + + /** + * @param int[]|string[] $data + */ + #[DataProvider('noneDataProvider')] + public function testNone(array $data, callable $filter, bool $expected): void + { + $this->assertSame( + $expected, + All::none($data, $filter) + ); + } + + /** + * @return Iterator + */ + public static function noneDataProvider(): Iterator + { + yield [ + [1, 2, 3], + static fn($datum): bool => $datum === 4, + true, + ]; + yield [ + [1, 2, 3], + static fn($datum): bool => $datum === 2, + false, + ]; + yield [ + ['abc', 'def'], + static fn(string $datum, int $key): bool => $key === 0 && $datum === 'abc', + false, + ]; + yield [ + [], + static fn($datum): bool => $datum !== null, + true, + ]; + } +}