From 02ca01e2b7803b666b0647167d9b1ed4fe664ba2 Mon Sep 17 00:00:00 2001 From: brekk Date: Tue, 2 Apr 2024 14:38:23 -1000 Subject: [PATCH] feat: add `difference` and `symmetricDifference` to List --- prelude/__internal__/List.mad | 24 +++++++++++++++++++++--- prelude/__internal__/List.spec.mad | 14 ++++++++++++++ 2 files changed, 35 insertions(+), 3 deletions(-) diff --git a/prelude/__internal__/List.mad b/prelude/__internal__/List.mad index 94caf449..b60c8728 100644 --- a/prelude/__internal__/List.mad +++ b/prelude/__internal__/List.mad @@ -790,9 +790,6 @@ export includes = (x, list) => where(list) { [a, ...xs] => a == x || includes(x, xs) } -// a == x ? true : includes(x, xs) - - /** * Drops n items from the given list. @@ -1087,3 +1084,24 @@ export cut = (a, xs) => { Nothing } } +/** + * Finds the set (i.e. no duplicates) of all elements in the first list not contained in the second list. + * @example + * difference([1,2,3,4], [7,6,5,4,3]) // [1,2] + * difference([7,6,5,4,3], [1,2,3,4]) // [7,6,5] + */ +difference :: Eq a => List a -> List a -> List a +export difference = (z, a) => reduce((stack, c) => includes(c, a) ? stack : [...stack, c], [], z) + +/** + * Finds the set (i.e. no duplicates) of all elements contained in the first or second list, but not both. + * @example + * symmetricDifference([1,2,3,4], [7,6,5,4,3]) // [1,2,7,6,5] + * symmetricDifference([7,6,5,4,3], [1,2,3,4]) // [7,6,5,1,2] + */ +symmetricDifference :: Eq a => List a -> List a -> List a +export symmetricDifference = (z, a) => reduce( + (stack, c) => includes(c, a) && includes(c, z) ? stack : [...stack, c], + [], + concat(z, a), +) diff --git a/prelude/__internal__/List.spec.mad b/prelude/__internal__/List.spec.mad index 1e330d80..08becd74 100644 --- a/prelude/__internal__/List.spec.mad +++ b/prelude/__internal__/List.spec.mad @@ -10,6 +10,7 @@ import { concat, contains, cut, + difference, drop, dropLast, dropWhile, @@ -38,6 +39,7 @@ import { sort, sortDesc, startsWith, + symmetricDifference, tail, tails, take, @@ -291,3 +293,15 @@ test("all - false", () => assertEquals(all((x) => x > 4, [1, 2, 10]), false)) test("cut", () => assertEquals(cut(5, range(1, 11)), Just(#[[1, 2, 3, 4, 5], [6, 7, 8, 9, 10]]))) test("cut - negative index", () => assertEquals(cut(-1, range(1, 11)), Nothing)) test("cut - invalid index", () => assertEquals(cut(16, range(1, 11)), Nothing)) + +test("difference", () => assertEquals(difference([1, 2, 3, 4], [7, 6, 5, 4, 3]), [1, 2])) +test("difference - swap", () => assertEquals(difference([7, 6, 5, 4, 3], [1, 2, 3, 4]), [7, 6, 5])) + +test( + "symmetricDifference", + () => assertEquals(symmetricDifference([1, 2, 3, 4], [7, 6, 5, 4, 3]), [1, 2, 7, 6, 5]), +) +test( + "symmetricDifference", + () => assertEquals(symmetricDifference([7, 6, 5, 4, 3], [1, 2, 3, 4]), [7, 6, 5, 1, 2]), +)