diff --git a/packages/fp/src/combinations/combinations.js b/packages/fp/src/combinations/combinations.js new file mode 100644 index 00000000..7dcdea9c --- /dev/null +++ b/packages/fp/src/combinations/combinations.js @@ -0,0 +1,9 @@ +import { reduce } from 'lodash/fp'; + +const appendTo = values => value => [...values, value]; + +export default reduce( + (accumulated, current) => + accumulated.flatMap(values => current.map(appendTo(values))), + [[]], +); diff --git a/packages/fp/src/combinations/combinations.test.js b/packages/fp/src/combinations/combinations.test.js new file mode 100644 index 00000000..0ff0c343 --- /dev/null +++ b/packages/fp/src/combinations/combinations.test.js @@ -0,0 +1,50 @@ +import combinations from './combinations'; + +describe('combinations', () => { + it('given arrays of same size, returns all combinations', () => { + const actual = combinations([ + [1, 2], + [3, 4], + [5, 6], + ]); + + const expected = [ + [1, 3, 5], + [1, 3, 6], + [1, 4, 5], + [1, 4, 6], + [2, 3, 5], + [2, 3, 6], + [2, 4, 5], + [2, 4, 6], + ]; + + expect(actual).toEqual(expected); + }); + + it('given arrays of different size, returns all combinations', () => { + const actual = combinations([ + [1, 2], + [3, 4, 5], + ]); + + const expected = [ + [1, 3], + [1, 4], + [1, 5], + [2, 3], + [2, 4], + [2, 5], + ]; + + expect(actual).toEqual(expected); + }); + + it('given one of the arrays is empty, returns no combinations', () => { + const actual = combinations([[1, 2], [], [3, 4, 5]]); + + const expected = []; + + expect(actual).toEqual(expected); + }); +});