Skip to content

Commit

Permalink
feat(core): add collect (#2626)
Browse files Browse the repository at this point in the history
  • Loading branch information
griest024 committed Nov 30, 2023
1 parent 7211acd commit 260332b
Show file tree
Hide file tree
Showing 3 changed files with 146 additions and 7 deletions.
129 changes: 129 additions & 0 deletions libs/core/src/utils/collect.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,129 @@
import { collect } from './collect';

interface Type {
children?: Type[];
}

const getChildren = (obj: Type) => obj?.children || [];

describe('@daffodil/core | collect', () => {
let root: Type;
let obj00: Type;
let obj01: Type;
let obj10: Type;
let obj11: Type;
let obj20: Type;
let obj21: Type;
let obj30: Type;
let obj31: Type;
let result: Type[];

beforeEach(() => {
obj30 = {};
obj31 = {};
obj20 = {};
obj21 = {
children: [obj30, obj31],
};
obj10 = {
children: [obj20],
};
obj11 = {
children: [obj21],
};
obj00 = {
children: [obj10, obj11],
};
obj01 = {};
root = {
children: [obj00, obj01],
};
});

describe('when depth is not specified', () => {
beforeEach(() => {
result = collect(root, getChildren);
});

it('should return the root and all children', () => {
expect(result).toContain(root);
expect(result).toContain(obj00);
expect(result).toContain(obj01);
expect(result).toContain(obj10);
expect(result).toContain(obj11);
expect(result).toContain(obj20);
expect(result).toContain(obj21);
expect(result).toContain(obj30);
expect(result).toContain(obj31);
});
});

describe('when depth is equal to the depth of the tree', () => {
beforeEach(() => {
result = collect(root, getChildren, 3);
});

it('should return the root and all children', () => {
expect(result).toContain(root);
expect(result).toContain(obj00);
expect(result).toContain(obj01);
expect(result).toContain(obj10);
expect(result).toContain(obj11);
expect(result).toContain(obj20);
expect(result).toContain(obj21);
expect(result).toContain(obj30);
expect(result).toContain(obj31);
});
});

describe('when depth is more than the depth of the tree', () => {
beforeEach(() => {
result = collect(root, getChildren, 5);
});

it('should return the root and all children', () => {
expect(result).toContain(root);
expect(result).toContain(obj00);
expect(result).toContain(obj01);
expect(result).toContain(obj10);
expect(result).toContain(obj11);
expect(result).toContain(obj20);
expect(result).toContain(obj21);
expect(result).toContain(obj30);
expect(result).toContain(obj31);
});
});

describe('when depth is less than the depth of the tree', () => {
beforeEach(() => {
result = collect(root, getChildren, 2);
});

it('should return the root and all children up to the specified depth', () => {
expect(result).toContain(root);
expect(result).toContain(obj00);
expect(result).toContain(obj01);
expect(result).toContain(obj10);
expect(result).toContain(obj11);
expect(result).toContain(obj20);
expect(result).toContain(obj21);
});

describe('and there is a circular reference', () => {
beforeEach(() => {
obj00.children = [...obj00.children, root];
result = collect(root, getChildren, 2);
});

it('should return the root and all children up to the specified depth and should not infinitely recurse', () => {
expect(result).toContain(root);
expect(result).toContain(obj00);
expect(result).toContain(obj01);
expect(result).toContain(obj10);
expect(result).toContain(obj11);
expect(result).toContain(obj20);
expect(result).toContain(obj21);
});
});
});
});
9 changes: 9 additions & 0 deletions libs/core/src/utils/collect.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
/**
* Recurses through a tree, collecting each element in that tree and returning it in an array.
* The value of getKey should be a field that contains a list of the same type of object.
* Accepts an optional depth argument which will limit the traversal. This should be used for trees with circular references.
*/
export const collect = <T>(obj: T, getChildren: (val: T) => T[], depth?: number): T[] =>
!depth || depth > 0
? [obj].concat(...getChildren(obj).map((child) => collect(child, getChildren, depth - 1)))
: [obj];
15 changes: 8 additions & 7 deletions libs/core/src/utils/public_api.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,14 @@
export * from './long-arithmetic';
export { collect } from './collect';
export { daffAdd } from './long-arithmetic';
export { daffSubtract } from './long-arithmetic';
export { daffMultiply } from './long-arithmetic';
export { daffArrayToDict } from './array-to-dict';
export { daffDivide } from './long-arithmetic';
export { daffMultiply } from './long-arithmetic';
export { daffSubtract } from './long-arithmetic';
export { randomSlice } from './random-slice';
export { randomSubset } from './random-subset';
export { range } from './range';
export { sample } from './sample';
export { shallowCompare } from './shallow-compare';
export { shuffle } from './shuffle';
export { randomSubset } from './random-subset';
export { randomSlice } from './random-slice';
export { daffArrayToDict } from './array-to-dict';
export { sample } from './sample';
export { unique } from './unique';
export * from './long-arithmetic';

0 comments on commit 260332b

Please sign in to comment.