Skip to content

Commit

Permalink
add cartesian operation
Browse files Browse the repository at this point in the history
  • Loading branch information
mo-ba committed Apr 22, 2024
1 parent c31526d commit 671f077
Show file tree
Hide file tree
Showing 6 changed files with 156 additions and 5 deletions.
2 changes: 1 addition & 1 deletion spec/core/array.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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',
Expand Down
15 changes: 12 additions & 3 deletions spec/core/array/operator/allCombinations.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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']);
Expand Down
113 changes: 113 additions & 0 deletions spec/core/array/operator/cartesian.spec.ts
Original file line number Diff line number Diff line change
@@ -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);
});

});


3 changes: 2 additions & 1 deletion src/array/operator/allCombinations.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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[]): [A][];
export function allCombinations<A, B>(a: A[], b: B[]): [A, B][];
export function allCombinations<A, B, C>(a: A[], b: B[], c: C[]): [A, B, C][];
Expand All @@ -12,7 +13,7 @@ export function allCombinations<A, B, C, D, E, F, G>(a: A[], b: B[], c: C[], d:
export function allCombinations<A, B, C, D, E, F, G, H>(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)
Expand Down
27 changes: 27 additions & 0 deletions src/array/operator/cartesian.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import {chunkBySize} from './chunkBySize';
import {allCombinations} from './allCombinations';

export function cartesian(): [];
export function cartesian<A>(a: A[]): [A][];
export function cartesian<A, B>(a: A[], b: B[]): [A, B][][];
export function cartesian<A, B, C>(a: A[], b: B[], c: C[]): [A, B, C][][][];
export function cartesian<A, B, C, D>(a: A[], b: B[], c: C[], d: D[]): [A, B, C, D][][][][];
export function cartesian<A, B, C, D, E>(a: A[], b: B[], c: C[], d: D[], e: E[]): [A, B, C, D, E][][][][][];
export function cartesian<A, B, C, D, E, F>(a: A[], b: B[], c: C[], d: D[], e: E[], f: F[]): [A, B, C, D, E, F][][][][][];
export function cartesian<A, B, C, D, E, F, G>(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, B, C, D, E, F, G, H>(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, B, C, D, E, F, G, H>(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;

}

1 change: 1 addition & 0 deletions src/array/operator/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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';
Expand Down

0 comments on commit 671f077

Please sign in to comment.