Skip to content

Commit

Permalink
add reshape
Browse files Browse the repository at this point in the history
  • Loading branch information
mo-ba committed Apr 28, 2024
1 parent 1344e31 commit c5b5682
Show file tree
Hide file tree
Showing 9 changed files with 242 additions and 36 deletions.
8 changes: 8 additions & 0 deletions docs/src/config-menu.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,10 @@ export default {
"text": "allPairs",
"link": "en/array/operator/allPairs"
},
{
"text": "cartesian",
"link": "en/array/operator/cartesian"
},
{
"text": "choose",
"link": "en/array/operator/choose"
Expand Down Expand Up @@ -134,6 +138,10 @@ export default {
"text": "reduce",
"link": "en/array/operator/reduce"
},
{
"text": "reshape",
"link": "en/array/operator/reshape"
},
{
"text": "skip",
"link": "en/array/operator/skip"
Expand Down
52 changes: 52 additions & 0 deletions docs/src/pages/en/array/operator/cartesian.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
---
title: cartesian
description: cartesian
layout: ../../../../layouts/MainLayout.astro
---

## Description
The `cartesian` function calculates the Cartesian product of multiple arrays. It takes a variable number of arrays as arguments and returns an array of arrays representing all possible combinations of elements from the input arrays.

## Parameters
- `...arrays`: Arrays of elements.

## Returns
An array of arrays representing the Cartesian product of the input arrays.

## Type

```ts
type cartesian = (dimensions: [number,]) => <A>(a: A[]) => [A][];
type cartesian = (dimensions: [number, number,]) => <A>(a: A[]) => [A][][];
//...
type cartesian = (dimensions: [number, number, number, number, number, number, number, number]) => <A>(a: A[]) => [A][][][][][][][][];
```


## Example
```typescript
import { cartesian } from './path/to/cartesian';

const result = cartesian([1, 2], ['a', 'b', 'c'], [true, false]);

console.log(result);
// Output: [
// [
// [[1,"a",true],[1,"a",false]],
// [[1,"b",true],[1,"b",false]],
// [[1,"c",true],[1,"c",false]]
// ],
// [
// [[2,"a",true],[2,"a",false]],
// [[2,"b",true],[2,"b",false]],
// [[2,"c",true],[2,"c",false]]
// ]
// ]
```



## See Also

- [allCombinations](./allCombinations)
- [reshape](./reshape)
50 changes: 50 additions & 0 deletions docs/src/pages/en/array/operator/reshape.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
---
title: reshape
description: reshape
layout: ../../../../layouts/MainLayout.astro
---

## Description
The `reshape` function is designed to reshape a flat array into a multi-dimensional array according to the specified dimensions. It takes an array of dimensions and returns a function that accepts a flat array as input and returns a multi-dimensional array based on the provided dimensions.

## Parameters
- `dimensions`: An array of numbers representing the desired dimensions for the output array.

## Returns
A function that takes an array as input and returns a multi-dimensional array based on the specified dimensions.

## Throws
- `Error`: If the total size of the dimensions does not match the length of the input array.

## Type

```ts
type reshape = (dimensions: [number,]) => <A>(a: A[]) => [A][];
type reshape = (dimensions: [number, number,]) => <A>(a: A[]) => [A][][];
//...
type reshape = (dimensions: [number, number, number, number, number, number, number, number]) => <A>(a: A[]) => [A][][][][][][][][];
```

## Example

```typescript
import { reshape } from 'fnxt/array';

const dimensions = [2, 3, 2];
const fn = reshape(dimensions);

const flatArray = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12];
const multiDimensionalArray = fn(flatArray);

console.log(multiDimensionalArray);
// Output: [
// [[1, 2], [3, 4], [5, 6]],
// [[7, 8], [9, 10], [11, 12]]
// ]
```


## See Also

- [allCombinations](./allCombinations)
- [cartesian](./cartesian)
48 changes: 20 additions & 28 deletions spec/core/array.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,34 +12,26 @@ describe('array', () => {

describe('operator', () => {
const operators = [
'allCombinations', 'allPairs', 'append',
'average', 'averageBy', 'cartesian','choose',
'chunkBySize', 'collect', 'compareWith',
'concat', 'contains', 'copy',
'countBy', 'distinctBy', 'every',
'exists', 'fill', 'filter',
'find', 'findBack', 'findIndex',
'findIndexBack', 'flatten', 'fold',
'foldBack', 'forall', 'groupBy', 'head',
'init', 'insertAt', 'interleave', 'isEmpty',
'iter', 'last', 'length',
'map', 'maxBy', 'minBy',
'pairwise','pairwiseWith', 'partition', 'push',
'reduce', 'reduceBack', 'replicate',
'rev', 'rotate', 'rotateBack',
'scan', 'scanBack', 'skip',
'skipWhile', 'sort', 'sortBy',
'sortByDescending', 'sortDescending', 'sortInPlace',
'sortInPlace', 'sortInPlaceBy', 'sortInPlaceWith',
'sortInPlaceWith', 'sortWith', 'sortWith',
'splitAt', 'splitInto', 'stride', 'strideWindowed',
'sum', 'sumBy', 'remove', 'tail', 'take',
'takeWhile', 'takeWhileInclusive', 'transpose',
'truncate', 'tryFind', 'tryFindBack',
'tryFindIndex', 'tryFindIndexBack', 'tryHead',
'tryLast', 'uniqueBy', 'updateAt',
'where', 'windowed', 'zip',
'zip3', 'zipWith'
/* A */ 'allCombinations', 'allPairs', 'append', 'average', 'averageBy',
/* C */ 'cartesian', 'choose', 'chunkBySize', 'collect', 'compareWith', 'concat', 'contains', 'copy', 'countBy',
/* D */ 'distinctBy',
/* E */ 'every', 'exists',
/* F */ 'fill', 'filter', 'find', 'findBack', 'findIndex', 'findIndexBack', 'flatten', 'fold', 'foldBack', 'forall',
/* G */ 'groupBy',
/* H */ 'head',
/* I */ 'init', 'insertAt', 'interleave', 'isEmpty', 'iter',
/* L */ 'last', 'length',
/* M */ 'map', 'maxBy', 'minBy',
/* P */ 'pairwise', 'pairwiseWith', 'partition', 'push',
/* R */ 'reduce', 'reduceBack', 'remove', 'replicate', 'reshape', 'rev', 'rotate', 'rotateBack',
/* S */ 'scan', 'scanBack', 'skip', 'skipWhile', 'sort', 'sortBy', 'sortByDescending', 'sortDescending',
'sortInPlace', 'sortInPlace', 'sortInPlaceBy', 'sortInPlaceWith', 'sortInPlaceWith', 'sortWith',
'sortWith', 'splitAt', 'splitInto', 'stride', 'strideWindowed', 'sum', 'sumBy',
/* T */ 'tail', 'take', 'takeWhile', 'takeWhileInclusive', 'transpose', 'truncate', 'tryFind', 'tryFindBack',
'tryFindIndex', 'tryFindIndexBack', 'tryHead', 'tryLast',
/* U */ 'uniqueBy', 'updateAt',
/* W */ 'where', 'windowed',
/* Z */ 'zip', 'zip3', 'zipWith'
]
.sort();
operators.map(name => './array/operator/' + name + '.spec')
Expand Down
16 changes: 16 additions & 0 deletions spec/core/array/operator/cartesian.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,22 @@ describe('cartesian', () => {
]);
});

it('should cartesian [1, 2], ["a", "b", "c"], [true, false]', () => {
console.log(JSON.stringify(cartesian([1, 2], ['a', 'b', 'c'], [true, false])));
expect(cartesian([1, 2], ['a', 'b', 'c'], [true, false])).to.eql([
[
[[1,"a",true],[1,"a",false]],
[[1,"b",true],[1,"b",false]],
[[1,"c",true],[1,"c",false]]
],
[
[[2,"a",true],[2,"a",false]],
[[2,"b",true],[2,"b",false]],
[[2,"c",true],[2,"c",false]]
]
]);
});

it('should cartesian [3,4,2]', () => {

const fn = cartesian;
Expand Down
60 changes: 60 additions & 0 deletions spec/core/array/operator/reshape.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
import {expect} from 'chai';
import {reshape} from '../../../../src/array/';

describe('reshape', () => {


it('should reshape []', () => {

const fn = reshape([]);
expect(fn([])).to.eql([]);
});

it('should reshape [1]', () => {

const fn = reshape([1]);
expect(fn([1])).to.eql([1]);
});

it('should reshape [2]', () => {

const fn = reshape([1, 2]);
expect(fn([1, 2])).to.eql([
[1, 2],
]);
});

it('should reshape [1,2]', () => {

const fn = reshape([1, 2]);
expect(fn([1, 2])).to.eql([
[1, 2],
]);
});
it('should reshape [2,3,2]', () => {

const fn = reshape([2, 3, 2]);
expect(fn([1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12])).to.eql(
[
[[1, 2], [3, 4], [5, 6]],
[[7, 8], [9, 10], [11, 12]]
]
);
});
it('should reshape [4, 3, 1]', () => {

const fn = reshape([4, 3, 1]);
expect(fn([1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12])).to.eql(
[[[1], [2], [3]], [[4], [5], [6]], [[7], [8], [9]], [[10], [11], [12]]]
);
});
it('should reshape [4, 3, 1]', () => {

const fn = reshape([4, 3, 1]);
expect(() => fn([0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12])).to.throws();
});


});


12 changes: 4 additions & 8 deletions src/array/operator/cartesian.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import {chunkBySize} from './chunkBySize';
import {allCombinations} from './allCombinations';
import {reshape} from './reshape';

export function cartesian(): [];
export function cartesian<A>(a: A[]): [A][];
Expand All @@ -15,13 +15,9 @@ export function cartesian<A, B, C, D, E, F, G, H>(a: A[], b: B[], c: C[], d: D[]
export function cartesian(...arrays: unknown[][]): unknown[][] {

// @ts-ignore
let res: any[] = allCombinations(...arrays);

for (let i = arrays.length - 1; i > 0; i--) {
const size = arrays[i].length;
res = chunkBySize(size)(res);
}
return res;
const res: any[] = allCombinations(...arrays);

const dimensions = arrays.map(a => a.length)
return reshape(dimensions)(res) as any[]
}

1 change: 1 addition & 0 deletions src/array/operator/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ export * from './reduce';
export * from './reduceBack';
export * from './remove';
export * from './replicate';
export * from './reshape';
export * from './rev';
export * from './rotate';
export * from './rotateBack';
Expand Down
31 changes: 31 additions & 0 deletions src/array/operator/reshape.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
import {chunkBySize} from './chunkBySize';

export function reshape(dimensions: [number,]): <A>(a: A[]) => [A][];
export function reshape(dimensions: [number, number,]): <A>(a: A[]) => [A][][];
export function reshape(dimensions: [number, number, number,]): <A>(a: A[]) => [A][][][];
export function reshape(dimensions: [number, number, number, number,]): <A>(a: A[]) => [A][][][][];
export function reshape(dimensions: [number, number, number, number, number,]): <A>(a: A[]) => [A][][][][][];
export function reshape(dimensions: [number, number, number, number, number, number,]): <A>(a: A[]) => [A][][][][][][];
export function reshape(dimensions: [number, number, number, number, number, number, number,]): <A>(a: A[]) => [A][][][][][][][];
export function reshape(dimensions: [number, number, number, number, number, number, number, number]): <A>(a: A[]) => [A][][][][][][][][];
export function reshape(dimensions: number[]): <A>(a: A[]) => any[];

export function reshape(dimensions: number[]) {
const size = dimensions.length ? dimensions.reduce((a, b) => a * b, 1) : 0;
return (arrays: unknown[]): unknown[] => {
if (size !== arrays.length) {
throw new Error(dimensions.join(' * ') + ' must equal array length');
}
if (size === 0) {
return [];
}
// @ts-ignore
let res: any[] = arrays;
for (let i = dimensions.length - 1; i >= 0; i--) {
res = chunkBySize(dimensions[i])(res);
}
return res[0];

};
}

0 comments on commit c5b5682

Please sign in to comment.