From 77e44f0804278e5ca56ac8a48c622fff21713952 Mon Sep 17 00:00:00 2001 From: Simon Podlipsky Date: Thu, 12 Sep 2024 17:38:29 +0200 Subject: [PATCH] feat: introduce search_with_keys and search_with_keys_opt Currently, there's no way to search iterable using also a key --- docs/component/iter.md | 3 +- src/Psl/Internal/Loader.php | 3 +- src/Psl/Iter/search_with_keys.php | 38 ++++++++++++++++ ...h_opt_k_v.php => search_with_keys_opt.php} | 6 +-- tests/unit/Iter/SearchWithKeysOptTest.php | 43 +++++++++++++++++++ ...chOptKVTest.php => SearchWithKeysTest.php} | 7 +-- 6 files changed, 92 insertions(+), 8 deletions(-) create mode 100644 src/Psl/Iter/search_with_keys.php rename src/Psl/Iter/{search_opt_k_v.php => search_with_keys_opt.php} (75%) create mode 100644 tests/unit/Iter/SearchWithKeysOptTest.php rename tests/unit/Iter/{SearchOptKVTest.php => SearchWithKeysTest.php} (83%) diff --git a/docs/component/iter.md b/docs/component/iter.md index 426cb51f..51481d88 100644 --- a/docs/component/iter.md +++ b/docs/component/iter.md @@ -34,7 +34,8 @@ - [rewindable](./../../src/Psl/Iter/rewindable.php#L20) - [search](./../../src/Psl/Iter/search.php#L28) - [search_opt](./../../src/Psl/Iter/search_opt.php#L30) -- [search_opt_k_v](./../../src/Psl/Iter/search_opt_k_v.php#L31) +- [search_with_keys](./../../src/Psl/Iter/search_with_keys.php#L29) +- [search_with_keys_opt](./../../src/Psl/Iter/search_with_keys_opt.php#L31) - [to_iterator](./../../src/Psl/Iter/to_iterator.php#L19) #### `Classes` diff --git a/src/Psl/Internal/Loader.php b/src/Psl/Internal/Loader.php index 7ebbb859..89c063d7 100644 --- a/src/Psl/Internal/Loader.php +++ b/src/Psl/Internal/Loader.php @@ -151,8 +151,9 @@ final class Loader 'Psl\\Iter\\reduce_with_keys' => 'Psl/Iter/reduce_with_keys.php', 'Psl\\Iter\\rewindable' => 'Psl/Iter/rewindable.php', 'Psl\\Iter\\search' => 'Psl/Iter/search.php', + 'Psl\\Iter\\search_with_keys' => 'Psl/Iter/search_with_keys.php', 'Psl\\Iter\\search_opt' => 'Psl/Iter/search_opt.php', - 'Psl\\Iter\\search_opt_k_v' => 'Psl/Iter/search_opt_k_v.php', + 'Psl\\Iter\\search_with_keys_opt' => 'Psl/Iter/search_with_keys_opt.php', 'Psl\\Iter\\to_iterator' => 'Psl/Iter/to_iterator.php', 'Psl\\Vec\\chunk' => 'Psl/Vec/chunk.php', 'Psl\\Vec\\chunk_with_keys' => 'Psl/Vec/chunk_with_keys.php', diff --git a/src/Psl/Iter/search_with_keys.php b/src/Psl/Iter/search_with_keys.php new file mode 100644 index 00000000..017de120 --- /dev/null +++ b/src/Psl/Iter/search_with_keys.php @@ -0,0 +1,38 @@ + 'baz' === $v) + * => 'baz' + * + * Iter\search_with_keys(['foo', 'bar', 'baz'], fn($k, $v) => 'qux' === $v) + * => null + * + * @template TKey + * @template TValue + * + * @param iterable $iterable The iterable to search + * @param (Closure(TKey, TValue): bool) $predicate + * + * @return TValue|null + */ +function search_with_keys(iterable $iterable, Closure $predicate): mixed +{ + foreach ($iterable as $key => $value) { + if ($predicate($key, $value)) { + return $value; + } + } + + return null; +} diff --git a/src/Psl/Iter/search_opt_k_v.php b/src/Psl/Iter/search_with_keys_opt.php similarity index 75% rename from src/Psl/Iter/search_opt_k_v.php rename to src/Psl/Iter/search_with_keys_opt.php index 2b9d57ea..f5386631 100644 --- a/src/Psl/Iter/search_opt_k_v.php +++ b/src/Psl/Iter/search_with_keys_opt.php @@ -14,10 +14,10 @@ * * Examples: * - * Iter\search_opt_k_v(['foo', 'bar', 'baz'], fn($k, $v) => 'baz' === $v) + * Iter\search_with_keys_opt(['foo', 'bar', 'baz'], fn($k, $v) => 'baz' === $v) * => Option::some('baz') * - * Iter\search_opt_k_v(['foo', 'bar', 'baz'], fn($k, $v) => 'qux' === $v) + * Iter\search_with_keys_opt(['foo', 'bar', 'baz'], fn($k, $v) => 'qux' === $v) * => Option::none() * * @template TKey @@ -28,7 +28,7 @@ * * @return Option */ -function search_opt_k_v(iterable $iterable, Closure $predicate): Option +function search_with_keys_opt(iterable $iterable, Closure $predicate): Option { foreach ($iterable as $key => $value) { if ($predicate($key, $value)) { diff --git a/tests/unit/Iter/SearchWithKeysOptTest.php b/tests/unit/Iter/SearchWithKeysOptTest.php new file mode 100644 index 00000000..34850a0a --- /dev/null +++ b/tests/unit/Iter/SearchWithKeysOptTest.php @@ -0,0 +1,43 @@ +unwrap()); + } + + public function provideDataSome(): iterable + { + yield ['baz', ['foo', 'bar', 'baz'], static fn (int $k, string $v): bool => 2 === $k && 'baz' === $v]; + + yield [ + 'baz', + Iter\to_iterator(['foo', 'bar', 'baz']), static fn (int $k, string $v): bool => 2 === $k && 'baz' === $v + ]; + } + /** + * @dataProvider provideDataNone + */ + public function testSearchNone(iterable $iterable, callable $predicate): void + { + static::assertTrue(Iter\search_with_keys_opt($iterable, $predicate)->isNone()); + } + + public function provideDataNone(): iterable + { + yield [[], static fn (int $k, string $v): bool => 'qux' === $v]; + yield [Iter\to_iterator([]), static fn (int $k, string $v): bool => 'qux' === $v]; + yield [Iter\to_iterator(['foo', 'bar', 'baz']), static fn (int $k, string $v): bool => 'qux' === $v]; + } +} diff --git a/tests/unit/Iter/SearchOptKVTest.php b/tests/unit/Iter/SearchWithKeysTest.php similarity index 83% rename from tests/unit/Iter/SearchOptKVTest.php rename to tests/unit/Iter/SearchWithKeysTest.php index 5dc6a166..aee40745 100644 --- a/tests/unit/Iter/SearchOptKVTest.php +++ b/tests/unit/Iter/SearchWithKeysTest.php @@ -7,14 +7,14 @@ use PHPUnit\Framework\TestCase; use Psl\Iter; -final class SearchOptKVTest extends TestCase +final class SearchWithKeysTest extends TestCase { /** * @dataProvider provideDataSome */ public function testSearchSome($expected, iterable $iterable, callable $predicate): void { - static::assertSame($expected, Iter\search_opt_k_v($iterable, $predicate)->unwrap()); + static::assertSame($expected, Iter\search_with_keys($iterable, $predicate)); } public function provideDataSome(): iterable @@ -31,8 +31,9 @@ public function provideDataSome(): iterable */ public function testSearchNone(iterable $iterable, callable $predicate): void { - static::assertTrue(Iter\search_opt_k_v($iterable, $predicate)->isNone()); + static::assertNull(Iter\search_with_keys($iterable, $predicate)); } + public function provideDataNone(): iterable { yield [[], static fn (int $k, string $v): bool => 'qux' === $v];