From 2af0f628d385c4bb95a0c285f1debdd9445635e5 Mon Sep 17 00:00:00 2001 From: Saif Eddin Gmati <29315886+azjezz@users.noreply.github.com> Date: Sat, 20 Feb 2021 20:48:20 +0100 Subject: [PATCH] [Dict] add intersect and diff functions (#137) --- src/Psl/Dict/diff.php | 42 +++++++++++++++++++++++++++ src/Psl/Dict/diff_by_key.php | 42 +++++++++++++++++++++++++++ src/Psl/Dict/intersect.php | 42 +++++++++++++++++++++++++++ src/Psl/Dict/intersect_by_key.php | 42 +++++++++++++++++++++++++++ src/Psl/Internal/Loader.php | 4 +++ src/Psl/Iter/chain.php | 5 ++++ src/Psl/Iter/diff_by_key.php | 5 ++++ tests/Psl/Dict/DiffByKeyTest.php | 34 ++++++++++++++++++++++ tests/Psl/Dict/DiffTest.php | 36 +++++++++++++++++++++++ tests/Psl/Dict/IntersectByKeyTest.php | 38 ++++++++++++++++++++++++ tests/Psl/Dict/IntersectTest.php | 38 ++++++++++++++++++++++++ 11 files changed, 328 insertions(+) create mode 100644 src/Psl/Dict/diff.php create mode 100644 src/Psl/Dict/diff_by_key.php create mode 100644 src/Psl/Dict/intersect.php create mode 100644 src/Psl/Dict/intersect_by_key.php create mode 100644 tests/Psl/Dict/DiffByKeyTest.php create mode 100644 tests/Psl/Dict/DiffTest.php create mode 100644 tests/Psl/Dict/IntersectByKeyTest.php create mode 100644 tests/Psl/Dict/IntersectTest.php diff --git a/src/Psl/Dict/diff.php b/src/Psl/Dict/diff.php new file mode 100644 index 0000000..673feff --- /dev/null +++ b/src/Psl/Dict/diff.php @@ -0,0 +1,42 @@ + $first + * @psalm-param iterable $second + * @psalm-param iterable ...$rest + * + * @psalm-return array + */ +function diff(iterable $first, iterable $second, iterable ...$rest): array +{ + if (Iter\is_empty($first)) { + return []; + } + + return array_diff(from_iterable($first), from_iterable($second), ...Vec\map( + $rest, + /** + * @template Tk of array-key + * @template Tv + * + * @param iterable $iterable + * + * @return array + */ + static fn(iterable $iterable): array => from_iterable($iterable) + )); +} diff --git a/src/Psl/Dict/diff_by_key.php b/src/Psl/Dict/diff_by_key.php new file mode 100644 index 0000000..92f08f8 --- /dev/null +++ b/src/Psl/Dict/diff_by_key.php @@ -0,0 +1,42 @@ + $first + * @psalm-param iterable $second + * @psalm-param iterable ...$rest + * + * @psalm-return array + */ +function diff_by_key(iterable $first, iterable $second, iterable ...$rest): array +{ + if (Iter\is_empty($first)) { + return []; + } + + return array_diff_key(from_iterable($first), from_iterable($second), ...Vec\map( + $rest, + /** + * @template Tk of array-key + * @template Tv + * + * @param iterable $iterable + * + * @return array + */ + static fn(iterable $iterable): array => from_iterable($iterable) + )); +} diff --git a/src/Psl/Dict/intersect.php b/src/Psl/Dict/intersect.php new file mode 100644 index 0000000..c82fe1f --- /dev/null +++ b/src/Psl/Dict/intersect.php @@ -0,0 +1,42 @@ + $first + * @param iterable $second + * @param iterable ...$rest + * + * @return array + */ +function intersect(iterable $first, iterable $second, iterable ...$rest): array +{ + if (Iter\is_empty($first)) { + return []; + } + + return array_intersect(from_iterable($first), from_iterable($second), ...Vec\map( + $rest, + /** + * @template Tk of array-key + * @template Tv + * + * @param iterable $iterable + * + * @return array + */ + static fn(iterable $iterable): array => from_iterable($iterable) + )); +} diff --git a/src/Psl/Dict/intersect_by_key.php b/src/Psl/Dict/intersect_by_key.php new file mode 100644 index 0000000..3d83405 --- /dev/null +++ b/src/Psl/Dict/intersect_by_key.php @@ -0,0 +1,42 @@ + $first + * @param iterable $second + * @param iterable ...$rest + * + * @return array + */ +function intersect_by_key(iterable $first, iterable $second, iterable ...$rest): array +{ + if (Iter\is_empty($first)) { + return []; + } + + return array_intersect_key(from_iterable($first), from_iterable($second), ...Vec\map( + $rest, + /** + * @template Tk of array-key + * @template Tv + * + * @param iterable $iterable + * + * @return array + */ + static fn(iterable $iterable): array => from_iterable($iterable) + )); +} diff --git a/src/Psl/Internal/Loader.php b/src/Psl/Internal/Loader.php index 8c42660..fb4e173 100644 --- a/src/Psl/Internal/Loader.php +++ b/src/Psl/Internal/Loader.php @@ -129,6 +129,10 @@ final class Loader 'Psl\Dict\take_while', 'Psl\Dict\unique', 'Psl\Dict\unique_by', + 'Psl\Dict\diff', + 'Psl\Dict\diff_by_key', + 'Psl\Dict\intersect', + 'Psl\Dict\intersect_by_key', 'Psl\Fun\after', 'Psl\Fun\identity', 'Psl\Fun\pipe', diff --git a/src/Psl/Iter/chain.php b/src/Psl/Iter/chain.php index a981f18..23b06a1 100644 --- a/src/Psl/Iter/chain.php +++ b/src/Psl/Iter/chain.php @@ -5,6 +5,7 @@ declare(strict_types=1); namespace Psl\Iter; use Generator; +use Psl\Vec; /** * Chains the iterables that were passed as arguments. @@ -23,6 +24,10 @@ use Generator; * @psalm-param iterable ...$iterables Iterables to chain * * @psalm-return Iterator + * + * @deprecated use `Vec\concat` instead. + * + * @see Vec\concat() */ function chain(iterable ...$iterables): Iterator { diff --git a/src/Psl/Iter/diff_by_key.php b/src/Psl/Iter/diff_by_key.php index 1354f77..a783ab4 100644 --- a/src/Psl/Iter/diff_by_key.php +++ b/src/Psl/Iter/diff_by_key.php @@ -5,6 +5,7 @@ declare(strict_types=1); namespace Psl\Iter; use Generator; +use Psl\Dict; /** * @psalm-template Tk @@ -15,6 +16,10 @@ use Generator; * @psalm-param iterable ...$rest * * @psalm-return Iterator + * + * @deprecated use `Dict\diff_by_key` instead. + * + * @see Dict\diff_by_key() */ function diff_by_key(iterable $first, iterable $second, iterable ...$rest): Iterator { diff --git a/tests/Psl/Dict/DiffByKeyTest.php b/tests/Psl/Dict/DiffByKeyTest.php new file mode 100644 index 0000000..8f659e9 --- /dev/null +++ b/tests/Psl/Dict/DiffByKeyTest.php @@ -0,0 +1,34 @@ + 2], []]; + yield [[1, 2], [1, 2], [], ['baz' => 1]]; + yield [[6 => 7, 7 => 8], Vec\range(1, 8), Vec\range(1, 6), []]; + yield [[7 => 8], Vec\range(1, 8), Vec\range(1, 6), [6 => 7]]; + } +} diff --git a/tests/Psl/Dict/DiffTest.php b/tests/Psl/Dict/DiffTest.php new file mode 100644 index 0000000..8a413f1 --- /dev/null +++ b/tests/Psl/Dict/DiffTest.php @@ -0,0 +1,36 @@ + 2], []]; + yield [[1 => 2], [1, 2], [], ['baz' => 1]]; + yield [[], [1, 2], ['foo' => 2], ['baz' => 1]]; + yield [[], [1, 2], ['foo' => 2], ['baz' => 1]]; + yield [[6 => 7, 7 => 8], Vec\range(1, 8), Vec\range(1, 6), []]; + yield [[7 => 8], Vec\range(1, 8), Vec\range(1, 6), [6 => 7]]; + } +} diff --git a/tests/Psl/Dict/IntersectByKeyTest.php b/tests/Psl/Dict/IntersectByKeyTest.php new file mode 100644 index 0000000..f42f4f3 --- /dev/null +++ b/tests/Psl/Dict/IntersectByKeyTest.php @@ -0,0 +1,38 @@ + 2], []]; + yield [[], [1, 2], [], ['baz' => 1]]; + yield [[], [1, 2], ['foo' => 2], ['baz' => 1]]; + yield [[], [1, 2], ['foo' => 2], ['baz' => 1]]; + yield [[], [1, 2], ['foo' => 2, 'baz' => 1]]; + yield [[1, 2, 3, 4, 5, 6], Vec\range(1, 8), Vec\range(1, 6)]; + yield [[], Vec\range(1, 8), Vec\range(1, 6), []]; + yield [[5 => 6], Vec\range(1, 8), Vec\range(1, 6), [5 => 6, 6 => 7]]; + } +} diff --git a/tests/Psl/Dict/IntersectTest.php b/tests/Psl/Dict/IntersectTest.php new file mode 100644 index 0000000..edfb546 --- /dev/null +++ b/tests/Psl/Dict/IntersectTest.php @@ -0,0 +1,38 @@ + 2], []]; + yield [[], [1, 2], [], ['baz' => 1]]; + yield [[], [1, 2], ['foo' => 2], ['baz' => 1]]; + yield [[], [1, 2], ['foo' => 2], ['baz' => 1]]; + yield [[1, 2], [1, 2], ['foo' => 2, 'baz' => 1]]; + yield [[1, 2, 3, 4, 5, 6], Vec\range(1, 8), Vec\range(1, 6)]; + yield [[], Vec\range(1, 8), Vec\range(1, 6), []]; + yield [[5 => 6], Vec\range(1, 8), Vec\range(1, 6), [5 => 6, 6 => 7]]; + } +}