diff --git a/spec/core/array.spec.ts b/spec/core/array.spec.ts
index 3da1e3c..b6da8e8 100644
--- a/spec/core/array.spec.ts
+++ b/spec/core/array.spec.ts
@@ -13,7 +13,7 @@ describe('array', () => {
describe('operator', () => {
const operators = [
'allCombinations', 'allPairs', 'append',
- 'average', 'averageBy', 'choose',
+ 'average', 'averageBy', 'cartesian','choose',
'chunkBySize', 'collect', 'compareWith',
'concat', 'contains', 'copy',
'countBy', 'distinctBy', 'every',
diff --git a/spec/core/array/operator/allCombinations.spec.ts b/spec/core/array/operator/allCombinations.spec.ts
index ecc1329..1a6e30d 100644
--- a/spec/core/array/operator/allCombinations.spec.ts
+++ b/spec/core/array/operator/allCombinations.spec.ts
@@ -5,16 +5,25 @@ import {checkThrow} from '../../../support/checkThrow';
describe('allCombinations', () => {
- it('should allCombinations', () => {
+ it('should allCombinations []', () => {
const fn = allCombinations;
- expect(fn([1, 2], ['a', 'b'], [4, 5])).to.eql([
+ expect(fn()).to.eql([]);
+ });
+ it('should allCombinations [2,2,2]', () => {
+
+ const fn = allCombinations;
+ expect(fn(
+ [1, 2],
+ ['a', 'b'],
+ [4, 5]
+ )).to.eql([
[1, 'a', 4], [1, 'a', 5], [1, 'b', 4], [1, 'b', 5],
[2, 'a', 4], [2, 'a', 5], [2, 'b', 4], [2, 'b', 5],
]);
});
- it('should allCombinations', () => {
+ it('should allCombinations [4,4,2]', () => {
const fn = allCombinations;
const expansion = fn(['ace', 'king', 'queen', 'jack'], ['hearts', 'spades', 'diamonds', 'clubs'], ['blue cover', 'red cover']);
diff --git a/spec/core/array/operator/cartesian.spec.ts b/spec/core/array/operator/cartesian.spec.ts
new file mode 100644
index 0000000..ef341a4
--- /dev/null
+++ b/spec/core/array/operator/cartesian.spec.ts
@@ -0,0 +1,113 @@
+import {expect} from 'chai';
+import {cartesian} from '../../../../src/array';
+import {checkThrow} from '../../../support/checkThrow';
+
+describe('cartesian', () => {
+
+
+ it('should cartesian []', () => {
+
+ const fn = cartesian;
+ expect(fn([])).to.eql([]);
+ });
+
+ it('should cartesian [2]', () => {
+
+ const fn = cartesian;
+ expect(fn([1, 2])).to.eql([
+ [1],
+ [2],
+ ]);
+ });
+ it('should cartesian [2,3]', () => {
+
+ const fn = cartesian;
+ expect(fn([1, 2], ['a', 'b', 'c'])).to.eql([
+ [
+ [1, 'a'],
+ [1, 'b'],
+ [1, 'c'],
+ ],
+ [
+ [2, 'a'],
+ [2, 'b'],
+ [2, 'c'],
+ ],
+ ]);
+ });
+
+ it('should cartesian [3,4,2]', () => {
+
+ const fn = cartesian;
+ type Cover = 'blue cover' | 'red cover'
+ type Color = 'hearts' | 'spades' | 'diamonds' | 'clubs'
+ type Value = 'ace' | 'king' | 'queen'
+ const covers: Cover[] = ['blue cover', 'red cover'];
+ const expansion = fn(['ace', 'king', 'queen'] as Value[], ['hearts', 'spades', 'diamonds', 'clubs'] as Color[], covers);
+ const expected: typeof expansion = [
+ [
+ [
+ ['ace', 'hearts', 'blue cover'],
+ ['ace', 'hearts', 'red cover'],],
+ [
+ ['ace', 'spades', 'blue cover'],
+ ['ace', 'spades', 'red cover'],
+ ],
+ [
+ ['ace', 'diamonds', 'blue cover'],
+ ['ace', 'diamonds', 'red cover'],
+ ],
+ [
+ ['ace', 'clubs', 'blue cover'],
+ ['ace', 'clubs', 'red cover'],
+ ],
+ ],
+ [
+ [
+ ['king', 'hearts', 'blue cover'],
+ ['king', 'hearts', 'red cover'],
+ ],
+ [
+ ['king', 'spades', 'blue cover'],
+ ['king', 'spades', 'red cover'],
+ ],
+ [
+ ['king', 'diamonds', 'blue cover'],
+ ['king', 'diamonds', 'red cover'],
+ ],
+ [
+ ['king', 'clubs', 'blue cover'],
+ ['king', 'clubs', 'red cover'],
+ ],
+ ],
+ [
+ [
+ ['queen', 'hearts', 'blue cover'],
+ ['queen', 'hearts', 'red cover'],
+ ],
+ [
+ ['queen', 'spades', 'blue cover'],
+ ['queen', 'spades', 'red cover'],
+ ],
+ [
+ ['queen', 'diamonds', 'blue cover'],
+ ['queen', 'diamonds', 'red cover'],
+ ],
+ [
+ ['queen', 'clubs', 'blue cover'],
+ ['queen', 'clubs', 'red cover'],
+ ],
+ ]
+ ];
+ expect(expansion).to.eql(expected);
+ });
+
+
+ it('should throw if null or undefined', () => {
+ const fn = (e: number[][]) => cartesian(e);
+ checkThrow(fn);
+ });
+
+});
+
+
diff --git a/src/array/operator/allCombinations.ts b/src/array/operator/allCombinations.ts
index bf6f0e1..4ba10c3 100644
--- a/src/array/operator/allCombinations.ts
+++ b/src/array/operator/allCombinations.ts
@@ -2,6 +2,7 @@ import {allPairs} from './allPairs';
import {map} from './map';
import {pipe} from 'fnxt/pipe';
+export function allCombinations(): [];
export function allCombinations(a: A[]): [A][];
export function allCombinations(a: A[], b: B[]): [A, B][];
export function allCombinations(a: A[], b: B[], c: C[]): [A, B, C][];
@@ -12,7 +13,7 @@ export function allCombinations(a: A[], b: B[], c: C[], d:
export function allCombinations(a: A[], b: B[], c: C[], d: D[], e: E[], f: F[], g: G[], h: H[]): [A, B, C, D, E, F, G, H][];
export function allCombinations(...arrays: unknown[][]): unknown[][] {
-
+ if (arrays.length === 0) return [];
const fn = ([head, ...tail]: unknown[][]): unknown[][] =>
tail.length
? pipe(fn, allPairs(head), map(([h, t]) => [h, ...t]))(tail)
diff --git a/src/array/operator/cartesian.ts b/src/array/operator/cartesian.ts
new file mode 100644
index 0000000..7177acf
--- /dev/null
+++ b/src/array/operator/cartesian.ts
@@ -0,0 +1,27 @@
+import {chunkBySize} from './chunkBySize';
+import {allCombinations} from './allCombinations';
+
+export function cartesian(): [];
+export function cartesian(a: A[]): [A][];
+export function cartesian(a: A[], b: B[]): [A, B][][];
+export function cartesian(a: A[], b: B[], c: C[]): [A, B, C][][][];
+export function cartesian(a: A[], b: B[], c: C[], d: D[]): [A, B, C, D][][][][];
+export function cartesian(a: A[], b: B[], c: C[], d: D[], e: E[]): [A, B, C, D, E][][][][][];
+export function cartesian(a: A[], b: B[], c: C[], d: D[], e: E[], f: F[]): [A, B, C, D, E, F][][][][][];
+export function cartesian(a: A[], b: B[], c: C[], d: D[], e: E[], f: F[], g: G[]): [A, B, C, D, E, F, G][][][][][][];
+export function cartesian(a: A[], b: B[], c: C[], d: D[], e: E[], f: F[], g: G[], h: H[]): [A, B, C, D, E, F, G, H][][][][][][][];
+export function cartesian(a: A[], b: B[], c: C[], d: D[], e: E[], f: F[], g: G[], h: H[]): [A, B, C, D, E, F, G, H][][][][][][][];
+
+export function cartesian(...arrays: unknown[][]): unknown[][] {
+
+ // @ts-ignore
+ let res: any[] = allCombinations(...arrays);
+
+ for (let i = arrays.length - 1; i > 0; i--) {
+ let size = arrays[i].length;
+ res = chunkBySize(size)(res);
+ }
+ return res;
+
+}
+
diff --git a/src/array/operator/index.ts b/src/array/operator/index.ts
index 581f02d..5aa030a 100644
--- a/src/array/operator/index.ts
+++ b/src/array/operator/index.ts
@@ -3,6 +3,7 @@ export * from './allPairs';
export * from './append';
export * from './average';
export * from './averageBy';
+export * from './cartesian';
export * from './choose';
export * from './chunkBySize';
export * from './collect';