Skip to content

Commit

Permalink
Merge branch 'main' into alpha
Browse files Browse the repository at this point in the history
  • Loading branch information
djcsdy committed Jan 14, 2022
2 parents fab52df + 524b670 commit ee383e0
Show file tree
Hide file tree
Showing 2 changed files with 169 additions and 10 deletions.
89 changes: 82 additions & 7 deletions index.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import {
contains,
dropWhile,
empty,
equal,
exclude,
excludeFirst,
excludeNull,
Expand All @@ -34,6 +35,7 @@ import {
mapKeyFirstBy,
maximum,
minimum,
only,
or,
partition,
partitionWhile,
Expand All @@ -46,6 +48,8 @@ import {
scanRight,
scanRight1,
slice,
sort,
sortBy,
split,
sum,
tail,
Expand Down Expand Up @@ -85,6 +89,12 @@ test("last", t => {
t.is(last([1, 2, 3]), 3);
});

test("only", t => {
t.is(only([]), null);
t.is(only([4]), 4);
t.is(only([3, 4, 5]), null);
});

test("empty", t => {
t.true(empty([]));
t.false(empty([1, 2, 3]));
Expand Down Expand Up @@ -120,6 +130,38 @@ test("dropWhile", t => {
);
});

test("equal", t => {
t.true(equal([1, 2, 3], [1, 2, 3]));
t.false(equal([1, 2, 3], [1, 2, 3, 4]));
t.false(equal([1, 2, 3, 4], [1, 2, 3]));
t.false(equal([1, 3, 3], [1, 2, 3]));
t.true(
equal(
[
[1, 2],
[3, 4]
],
[
[1, 2],
[3, 4]
],
equal
)
);
t.false(
equal(
[
[1, 2],
[3, 4]
],
[
[1, 2],
[3, 4]
]
)
);
});

test("map", t => {
t.deepEqual(
map([1, 2, 3], e => e + 1),
Expand Down Expand Up @@ -450,24 +492,57 @@ test("mapKeyBy", t => {
t.deepEqual(Array.from(map.keys()), ["odd", "even"]);
});

test("mapKeyFirstBy", t => {
const map = mapKeyFirstBy([1, 3, 4, 2, 5, 6], e => [e % 2 === 0 ? "even" : "odd", String(e)]);
t.is(map.get("even"), "4");
t.is(map.get("odd"), "1");
t.deepEqual(Array.from(map.keys()), ["odd", "even"]);
});

test("groupByIdentity", t => {
t.deepEqual(
groupByIdentity(["abc", "adef", "bghi"], a => a.substr(0, 1)),
[["abc", "adef"], ["bghi"]]
);
});

test("sort", t => {
t.deepEqual(sort([2, 4, 3, 1]), [1, 2, 3, 4]);
t.deepEqual(sort(["hello", "goodbye"]), ["goodbye", "hello"]);
t.deepEqual(
sort([-2, 4, -3, 1], (a, b) => Math.abs(a) - Math.abs(b)),
[1, -2, -3, 4]
);
});

test("sortBy", t => {
t.deepEqual(
sortBy(
[
{x: "a", y: 2},
{x: "b", y: 4},
{x: "c", y: 3},
{x: "d", y: 1}
],
({y}) => y
),
[
{x: "d", y: 1},
{x: "a", y: 2},
{x: "c", y: 3},
{x: "b", y: 4}
]
);
t.deepEqual(
sortBy([-2, 4, -3, 1], e => Math.abs(e)),
[1, -2, -3, 4]
);
});

test("forEach", t => {
const a = ["a", "b", "c"];
let s = "";
const b = forEach(a, c => (s += c));
t.is(b, a);
t.is(s, "abc");
});

test("mapKeyFirstBy", t => {
const map = mapKeyFirstBy([1, 3, 4, 2, 5, 6], e => [e % 2 === 0 ? "even" : "odd", String(e)]);
t.is(map.get("even"), "4");
t.is(map.get("odd"), "1");
t.deepEqual(Array.from(map.keys()), ["odd", "even"]);
});
90 changes: 87 additions & 3 deletions index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,12 @@ export function last<T>(array: ArrayLike<T>): T | null {
return array.length === 0 ? null : array[array.length - 1];
}

/** If the array contains exactly one element, returns that element.
* Otherwise, returns null. */
export function only<T>(array: ArrayLike<T>): T | null {
return array.length === 1 ? array[0] : null;
}

export function empty<T>(array: ArrayLike<T>): boolean {
return array.length === 0;
}
Expand Down Expand Up @@ -182,6 +188,50 @@ export function dropWhileFn<T>(
return array => dropWhile(array, predicate);
}

export function equal<T>(
a: ArrayLike<T>,
b: ArrayLike<T>,
elementsEqual: (a: T, b: T) => boolean = defaultEqual
): boolean {
if (a.length !== b.length) {
return false;
}

for (let i = 0; i < a.length; ++i) {
if (!elementsEqual(a[i], b[i])) {
return false;
}
}

return true;
}

export function equalFn<T>(
b: ArrayLike<T>,
elementsEqual: (a: T, b: T) => boolean = defaultEqual
): (a: ArrayLike<T>) => boolean {
return a => equal(a, b, elementsEqual);
}

export function notEqual<T>(
a: ArrayLike<T>,
b: ArrayLike<T>,
elementsEqual: (a: T, b: T) => boolean = defaultEqual
): boolean {
return !equal(a, b, elementsEqual);
}

export function notEqualFn<T>(
b: ArrayLike<T>,
elementsEqual: (a: T, b: T) => boolean = defaultEqual
): (a: ArrayLike<T>) => boolean {
return a => notEqual(a, b, elementsEqual);
}

function defaultEqual(a: unknown, b: unknown): boolean {
return a === b;
}

// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore duplicate identifier: This is the exported declaration, the implementation is below.
export function map<T, U>(array: ArrayLike<T>, f: (element: T, index: number) => U): U[];
Expand Down Expand Up @@ -792,9 +842,10 @@ export function partitionWhileFn<T>(
* If one of the supplied arrays is shorter than the other, then the excess
* elements of the longer array will be discarded. */
export function zip<T, U>(a: readonly T[], b: readonly U[]): Array<[T, U]> {
const result: Array<[T, U]> = [];
for (let i = 0; i < a.length && i < b.length; ++i) {
result.push([a[i], b[i]]);
const length = Math.min(a.length, b.length);
const result = new Array<[T, U]>(length);
for (let i = 0; i < length; ++i) {
result[i] = [a[i], b[i]];
}
return result;
}
Expand Down Expand Up @@ -1463,6 +1514,39 @@ export function shuffle<T>(array: ArrayLike<T>): T[] {
return result;
}

export function sort(array: ArrayLike<boolean>): boolean[];
export function sort(array: ArrayLike<number>): number[];
export function sort(array: ArrayLike<string>): string[];
export function sort<T>(array: ArrayLike<T>, comparator: Comparator<T>): T[];
export function sort<T>(array: ArrayLike<T>, comparator?: Comparator<T>): T[] {
return copy(array).sort(comparator ?? (defaultCompare as any));
}

export function sortFn<T>(comparator: Comparator<T>): (array: ArrayLike<T>) => T[] {
return array => sort(array, comparator);
}

export function sortBy<T>(array: ArrayLike<T>, select: SortSelect<T>): T[] {
return sort(array, (a, b) => defaultCompare(select(a) as any, select(b) as any));
}

export function sortByFn<T>(select: SortSelect<T>): (array: ArrayLike<T>) => T[] {
return array => sortBy(array, select);
}

export function sortByDescending<T>(array: ArrayLike<T>, select: SortSelect<T>): T[] {
return sort(array, (a, b) => -defaultCompare(select(a) as any, select(b) as any));
}

export function sortByDescendingFn<T>(select: SortSelect<T>): (array: ArrayLike<T>) => T[] {
return array => sortByDescending(array, select);
}

export type SortSelect<T> =
| ((element: T) => boolean)
| ((element: T) => number)
| ((element: T) => string);

export function forEach<T>(
array: ArrayLike<T>,
f: (element: T, index: number) => void
Expand Down

0 comments on commit ee383e0

Please sign in to comment.