Skip to content

Commit

Permalink
feat: added ks.union(other)
Browse files Browse the repository at this point in the history
  • Loading branch information
eturino committed Feb 4, 2021
1 parent a213b52 commit cde30b5
Show file tree
Hide file tree
Showing 12 changed files with 361 additions and 1 deletion.
8 changes: 8 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -143,6 +143,14 @@ Returns a new KeySet with the intersection of both Sets `(A ∩ B)`, representin
const diffKeySet = keySet.intersect(other);
```

### `union(other)`

Returns a new KeySet with the union of both Sets `(A U B)`, representing the elements present in either A or B

```ts
const diffKeySet = keySet.intersect(other);
```

### `includes(element)`

alias `contains(element)`.
Expand Down
6 changes: 6 additions & 0 deletions src/lib/key-set/-base.ts
Original file line number Diff line number Diff line change
Expand Up @@ -146,6 +146,12 @@ export interface IKeySetClass<T extends Key> {
*/
intersect(other: KeySet): KeySet;

/**
* returns a new KeySet with the union of both Sets (A U B), representing the elements present in either A or B
* @param other
*/
union(other: KeySet): KeySet;

/**
* returns a boolean if the KeySet includes the given element
*
Expand Down
2 changes: 2 additions & 0 deletions src/lib/key-set/-by-keys.ts
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,8 @@ export abstract class KeySetByKeys<T extends Key> implements IKeySetClass<T> {

public abstract intersect(other: KeySet | KeySetGlobal<Key>): KeySet;

public abstract union(other: KeySet | KeySetGlobal<Key>): KeySet;

public abstract includes(element: T): boolean;

public contains(element: T): boolean {
Expand Down
2 changes: 2 additions & 0 deletions src/lib/key-set/-global.ts
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,8 @@ export abstract class KeySetGlobal<T extends Key> implements IKeySetClass<T> {

public abstract intersect(other: KeySet | KeySetGlobal<Key>): KeySet;

public abstract union(other: KeySet | KeySetGlobal<Key>): KeySet;

public abstract includes(element: T): boolean;

public contains(element: T): boolean {
Expand Down
92 changes: 92 additions & 0 deletions src/lib/key-set/__tests__/union/all-except-some.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
import { KeySetAll, KeySetAllExceptSome, KeySetNone, KeySetSome } from "../../../..";

const keySetAll = new KeySetAll<number>();
const keySetNone = new KeySetNone<number>();

const subSetKeys = [1, 2];
const restKeys = [3];
const keys = [...subSetKeys, ...restKeys];
const extraKeys = [4];
const moreKeys = [...keys, ...extraKeys];
const otherKeys = [5, 6];

const keySetSomeSameKeys = new KeySetSome(keys);
const keySetSomeSubSetKeys = new KeySetSome(subSetKeys);
const keySetSomeMoreKeys = new KeySetSome(moreKeys);
const keySetSomeDiffKeys = new KeySetSome(otherKeys);

const keySetAllExceptSomeSameKeys = new KeySetAllExceptSome(keys);
const keySetAllExceptSomeSubSetKeys = new KeySetAllExceptSome(subSetKeys);
const keySetAllExceptSomeMoreKeys = new KeySetAllExceptSome(moreKeys);
const keySetAllExceptSomeDiffKeys = new KeySetAllExceptSome(otherKeys);

const keySet = new KeySetAllExceptSome(keys); // => keys 1, 2, 3

// ALL

test("#union(keySetAll)", () => {
const rest = keySet.union(keySetAll);
expect(rest instanceof KeySetAll).toBeTruthy();
});

// NONE

test("#union(keySetNone)", () => {
const rest = keySet.union(keySetNone);
expect(rest instanceof KeySetAllExceptSome).toBeTruthy();
expect(rest.keys).toEqual(keys);
});

// SOME

test("#union(keySetSomeSameKeys)", () => {
const rest = keySet.union(keySetSomeSameKeys);
expect(rest instanceof KeySetAll).toBeTruthy();
});

test("#union(keySetSomeSubSetKeys)", () => {
const rest = keySet.union(keySetSomeSubSetKeys);
expect(rest instanceof KeySetAllExceptSome).toBeTruthy();
expect(rest.keys).toEqual(restKeys);
});

test("#union(keySetSomeMoreKeys)", () => {
const rest = keySet.union(keySetSomeMoreKeys);
expect(rest instanceof KeySetAll).toBeTruthy();
});

test("#union(keySetSomeDiffKeys)", () => {
const rest = keySet.union(keySetSomeDiffKeys);
expect(rest instanceof KeySetAllExceptSome).toBeTruthy();
expect(rest.keys).toEqual(keys);
});

// ALL EXCEPT SOME

test("#union(keySetAllExceptSomeSameKeys)", () => {
const rest = keySet.union(keySetAllExceptSomeSameKeys);
expect(rest instanceof KeySetAllExceptSome).toBeTruthy();
expect(keySet === rest).toBe(false);
expect(rest.keys).toEqual(keys);
});

test("#union(keySetAllExceptSomeSubSetKeys)", () => {
const rest = keySet.union(keySetAllExceptSomeSubSetKeys);
expect(rest instanceof KeySetAllExceptSome).toBeTruthy();
expect(keySet === rest).toBe(false);
const r = rest as KeySetAllExceptSome<number>;
expect(r.keys).toEqual(subSetKeys);
});

test("#union(keySetAllExceptSomeMoreKeys)", () => {
const rest = keySet.union(keySetAllExceptSomeMoreKeys);
expect(rest instanceof KeySetAllExceptSome).toBeTruthy();
expect(keySet === rest).toBe(false);
const r = rest as KeySetAllExceptSome<number>;
expect(r.keys).toEqual(keys);
});

test("#union(keySetAllExceptSomeDiffKeys)", () => {
const rest = keySet.union(keySetAllExceptSomeDiffKeys);
expect(rest instanceof KeySetAll).toBeTruthy();
});
38 changes: 38 additions & 0 deletions src/lib/key-set/__tests__/union/all.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
import { InvalidKeySetError, KeySetAll, KeySetAllExceptSome, KeySetNone, KeySetSome } from "../../../..";

const keySetAll = new KeySetAll();
const keySetNone = new KeySetNone();
const keySetSome = new KeySetSome([1, 2, 3]);
const keySetAllExceptSome = new KeySetAllExceptSome([1, 2, 3]);

const keySet = new KeySetAll();

test("#union(keySetAll)", () => {
const rest = keySet.union(keySetAll);
expect(rest instanceof KeySetAll).toBeTruthy();
expect(keySet).not.toBe(rest);
});

test("#union(keySetNone)", () => {
const rest = keySet.union(keySetNone);
expect(rest instanceof KeySetAll).toBeTruthy();
expect(keySet).not.toBe(rest);
});

test("#union(keySetSome)", () => {
const rest = keySet.union(keySetSome);
expect(rest instanceof KeySetAll).toBeTruthy();
expect(keySet).not.toBe(rest);
});

test("#union(keySetAllExceptSome)", () => {
const rest = keySet.union(keySetAllExceptSome);
expect(rest instanceof KeySetAll).toBeTruthy();
expect(keySet).not.toBe(rest);
});

test("#union(somethingInvalid)", () => {
expect(() => {
keySet.union((null as unknown) as KeySetAll);
}).toThrowError(InvalidKeySetError);
});
42 changes: 42 additions & 0 deletions src/lib/key-set/__tests__/union/none.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
import { InvalidKeySetError, KeySetAll, KeySetAllExceptSome, KeySetNone, KeySetSome } from "../../../..";

const keySetAll = new KeySetAll();
const keySetNone = new KeySetNone();
const keySetSome = new KeySetSome([1, 2, 3]);
const keySetAllExceptSome = new KeySetAllExceptSome([1, 2, 3]);

const keySet = new KeySetNone();

test("#union(keySetAll)", () => {
const rest = keySet.union(keySetAll);
expect(rest instanceof KeySetAll).toBeTruthy();
expect(keySet).not.toBe(rest);
});

test("#union(keySetNone)", () => {
const rest = keySet.union(keySetNone);
expect(rest instanceof KeySetNone).toBeTruthy();
expect(keySet).not.toBe(rest);
});

test("#union(keySetSome)", () => {
const rest = keySet.union(keySetSome);
expect(rest instanceof KeySetSome).toBeTruthy();

const r = rest as KeySetSome<number>;
expect(r.keys).toEqual(keySetSome.keys);
});

test("#union(keySetAllExceptSome)", () => {
const rest = keySet.union(keySetAllExceptSome);
expect(rest instanceof KeySetAllExceptSome).toBeTruthy();

const r = rest as KeySetAllExceptSome<number>;
expect(r.keys).toEqual(keySetAllExceptSome.keys);
});

test("#union(somethingInvalid)", () => {
expect(() => {
keySet.union((null as unknown) as KeySetAll);
}).toThrowError(InvalidKeySetError);
});
98 changes: 98 additions & 0 deletions src/lib/key-set/__tests__/union/some.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
import { KeySetAll, KeySetAllExceptSome, KeySetNone, KeySetSome } from "../../../..";

const keySetAll = new KeySetAll<number>();
const keySetNone = new KeySetNone<number>();

const subSetKeys = [1, 2];
const restKeys = [3];
const keys = [...subSetKeys, ...restKeys];
const extraKeys = [4];
const moreKeys = [...keys, ...extraKeys];
const otherKeys = [5, 6];

const keySetSomeSameKeys = new KeySetSome(keys);
const keySetSomeSubSetKeys = new KeySetSome(subSetKeys);
const keySetSomeMoreKeys = new KeySetSome(moreKeys);
const keySetSomeDiffKeys = new KeySetSome(otherKeys);

const keySetAllExceptSomeSameKeys = new KeySetAllExceptSome(keys);
const keySetAllExceptSomeSubSetKeys = new KeySetAllExceptSome(subSetKeys);
const keySetAllExceptSomeMoreKeys = new KeySetAllExceptSome(moreKeys);
const keySetAllExceptSomeDiffKeys = new KeySetAllExceptSome(otherKeys);

const keySet = new KeySetSome(keys); // => keys 1, 2, 3

// ALL

test("#union(keySetAll)", () => {
const rest = keySet.union(keySetAll);
expect(rest instanceof KeySetAll).toBeTruthy();
});

// NONE

test("#union(keySetNone)", () => {
const rest = keySet.union(keySetNone);
expect(rest instanceof KeySetSome).toBeTruthy();
expect(rest.keys).toEqual(keySet.keys);
});

// SOME

test("#union(keySetSomeSameKeys)", () => {
const rest = keySet.union(keySetSomeSameKeys);
expect(rest instanceof KeySetSome).toBeTruthy();
expect(keySet === rest).toBe(false);
const r = rest as KeySetSome<number>;
expect(r.keys).toEqual(keySet.keys);
});

test("#union(keySetSomeSubSetKeys)", () => {
const rest = keySet.union(keySetSomeSubSetKeys);
expect(rest instanceof KeySetSome).toBeTruthy();
expect(keySet === rest).toBe(false);
const r = rest as KeySetSome<number>;
expect(r.keys).toEqual(keySet.keys);
});

test("#union(keySetSomeMoreKeys)", () => {
const rest = keySet.union(keySetSomeMoreKeys);
expect(rest instanceof KeySetSome).toBeTruthy();
expect(keySet === rest).toBe(false);
const r = rest as KeySetSome<number>;
expect(r.keys).toEqual(moreKeys);
});

test("#union(keySetSomeDiffKeys)", () => {
const rest = keySet.union(keySetSomeDiffKeys);
expect(rest instanceof KeySetSome).toBeTruthy();
expect(keySet === rest).toBe(false);
const r = rest as KeySetSome<number>;
expect(r.keys).toEqual([...keys, ...otherKeys].sort());
});

// ALL EXCEPT SOME

test("#union(keySetAllExceptSomeSameKeys)", () => {
const rest = keySet.union(keySetAllExceptSomeSameKeys);
expect(rest instanceof KeySetAll).toBeTruthy();
});

test("#union(keySetAllExceptSomeSubSetKeys)", () => {
const rest = keySet.union(keySetAllExceptSomeSubSetKeys);
expect(rest instanceof KeySetAll).toBeTruthy();
});

test("#union(keySetAllExceptSomeMoreKeys)", () => {
const rest = keySet.union(keySetAllExceptSomeMoreKeys);
expect(rest instanceof KeySetAllExceptSome).toBeTruthy();
const r = rest as KeySetAllExceptSome<number>;
expect(r.keys).toEqual(extraKeys);
});

test("#union(keySetAllExceptSomeDiffKeys)", () => {
const rest = keySet.union(keySetAllExceptSomeDiffKeys);
expect(rest instanceof KeySetAllExceptSome).toBeTruthy();
const r = rest as KeySetAllExceptSome<number>;
expect(r.keys).toEqual(otherKeys);
});
24 changes: 24 additions & 0 deletions src/lib/key-set/all-except-some.ts
Original file line number Diff line number Diff line change
Expand Up @@ -87,9 +87,33 @@ export class KeySetAllExceptSome<T extends Key> extends KeySetByKeys<T> {
return allExceptSome([...this.keys, ...otherKeys]);
}

public union(other: KeySetAll<T> | KeySetAll<Key>): KeySetAll<T>;
public union(other: KeySetNone<T> | KeySetNone<Key>): KeySetAllExceptSome<T>;
public union(other: KeySet<T> | KeySetGlobal<Key>): KeySetAll<T> | KeySetAllExceptSome<T>;
public union(other: KeySet<T> | KeySetGlobal<Key>): KeySetAll<T> | KeySetAllExceptSome<T> {
if (other instanceof KeySetAll) return new KeySetAll();
if (other instanceof KeySetNone) return new KeySetAllExceptSome([...this.keys]);

const otherKeys = other.keys as T[];

if (other instanceof KeySetSome) {
return allExceptSome(this.excludeKeys(otherKeys));
}

return allExceptSome(this.intersectKeys(otherKeys));
}

private intersectKeys(otherKeys: T[]) {
return [...this.keys].filter((key) => otherKeys.includes(key));
}

private excludeMyKeys(keys: T[]) {
return [...keys].filter((key) => !this.keys.includes(key as T));
}

private excludeKeys(otherKeys: T[]) {
return [...this.keys].filter((key) => !otherKeys.includes(key));
}
}

/**
Expand Down
9 changes: 9 additions & 0 deletions src/lib/key-set/all.ts
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,15 @@ export class KeySetAll<T extends Key = Key> extends KeySetGlobal<T> {

throw new InvalidKeySetError(`other key set not recognised ${other}`);
}

public union(other: KeySet<T> | KeySetGlobal<Key>): KeySetAll<T> {
if (other instanceof KeySetAll) return new KeySetAll();
if (other instanceof KeySetNone) return new KeySetAll();
if (other instanceof KeySetSome) return new KeySetAll();
if (other instanceof KeySetAllExceptSome) return new KeySetAll();

throw new InvalidKeySetError(`other key set not recognised ${other}`);
}
}

export function all<T extends Key = Key>(): KeySetAll<T> {
Expand Down
Loading

0 comments on commit cde30b5

Please sign in to comment.