Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changeset/fruity-cobras-find.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"sortman": major
---

Fix sort args type
5 changes: 5 additions & 0 deletions .changeset/icy-brooms-call.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"sortman": major
---

Fix readme's code template
5 changes: 5 additions & 0 deletions .changeset/lucky-results-take.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"sortman": major
---

Fix benchmark algorithm and test code
10 changes: 3 additions & 7 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -37,8 +37,7 @@ const data = [
}
];

const sorted = SortMan.sort({
arr: data,
const sorted = SortMan.sort(data, {
func: (e) => e.i
});

Expand Down Expand Up @@ -67,11 +66,8 @@ import { SortMan } from "sortman";

const data = [200, 300, 100];

const sorted = SortMan.sort({
arr: data,
options: {
desc: true
}
const sorted = SortMan.sort(data, {
desc: true
});

console.log(sorted);
Expand Down
7 changes: 4 additions & 3 deletions benchmarks/sort.bench.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,11 +13,12 @@ for (const { name, algorithm } of sorts) {
algorithm.sort(numArrData);
});
bench("Number array in option", () => {
algorithm.sort({ arr: numArrData });
algorithm.sort(objectArrData, {
func: (e) => e.num
});
});
bench("Object array", () => {
algorithm.sort({
arr: objectArrData,
algorithm.sort(objectArrData, {
func: (e) => e.num
});
});
Expand Down
64 changes: 26 additions & 38 deletions src/Sort/SortBase.ts
Original file line number Diff line number Diff line change
@@ -1,28 +1,21 @@
import { z } from "zod";
import { inversion } from "../utils/array";

export type SortOptions = {
desc?: boolean;
};

export type SortNumArr = {
arr: number[];
options?: SortOptions;
};

export type SortNotNumArr<T> = {
arr: T[];
func: (e: T) => number;
options?: SortOptions;
};

export type SortElement<T> = T extends number ? T[] | SortNumArr : SortNotNumArr<T>;

export type SortCoreElement<T> = Array<{
num: number;
content: T;
}>;

export type SortOptionsFunc<T> = {
func: (e: T) => number;
};

export type SortOptions<T> = (T extends number
? Partial<SortOptionsFunc<T>>
: Required<SortOptionsFunc<T>>) & {
desc?: boolean;
};

export abstract class SortBase {
private isNumArray(arr: unknown): arr is number[] {
try {
Expand All @@ -33,30 +26,24 @@ export abstract class SortBase {
}
}

private getOptions<T>(content: SortElement<T>): SortOptions {
if (content instanceof Array) {
return {};
} else {
return content.options ?? {};
}
}

public sort<T>(content: SortElement<T>): T[] {
const options = this.getOptions(content);
public sort<T extends number>(arr: T[]): T[];
public sort<T>(arr: T[], options: SortOptions<T>): T[];
public sort<T>(arr: T[], options?: SortOptions<T>): T[] {
const elements = (() => {
if (content instanceof Array) {
return content.map((value) => {
return { num: value, content: value as T };
});
}
if (this.isNumArray(content.arr)) {
return content.arr.map((value) => {
return { num: value, content: value as T };
if (this.isNumArray(arr)) {
return arr.map((value) => {
return {
num: (options && options.func ? options.func(value) : value) as number,
content: value
};
});
} else {
const { arr, func } = content as SortNotNumArr<T>;
const { func } = options as SortOptionsFunc<T>;
return arr.map((value) => {
return { num: func(value), content: value };
return {
num: func(value),
content: value
};
});
}
})() satisfies SortCoreElement<T>;
Expand All @@ -67,11 +54,12 @@ export abstract class SortBase {

const result = this.core(elements).map(({ content }) => content);

if (options.desc) {
if (options && options.desc) {
return inversion(result);
}

return result;
}

public abstract core<T>(content: SortCoreElement<T>): SortCoreElement<T>;
}
10 changes: 6 additions & 4 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import { MergeSort } from "./Sort/MergeSort";
import { HeapSort } from "./Sort/HeapSort";
import { ShellSort } from "./Sort/ShellSort";

import type { SortElement } from "./Sort/SortBase";
import type { SortOptions } from "./Sort/SortBase";

export class SortMan {
public static readonly bogo = new BogoSort();
Expand All @@ -19,11 +19,13 @@ export class SortMan {
public static readonly insertion = new InsertionSort();
public static readonly selection = new SelectionSort();

public static sort<T>(content: SortElement<T>): T[] {
public static sort<T extends number>(arr: T[]): T[];
public static sort<T>(arr: T[], options: SortOptions<T>): T[];
public static sort<T>(arr: T[], options?: SortOptions<T>): T[] {
try {
return this.merge.sort(content);
return this.merge.sort(arr, options as SortOptions<T>);
} catch {
return this.insertion.sort(content);
return this.insertion.sort(arr, options as SortOptions<T>);
}
}
}
14 changes: 5 additions & 9 deletions tests/sort.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,26 +11,22 @@ for (const { name, algorithm, options } of sorts) {
expect(sortCheck(result)).toBe(true);
});
test("Number array with options", () => {
const result = algorithm.sort({
arr: numArrData
const result = algorithm.sort(numArrData, {
func: (e) => e
});
expect(sortCheck(result)).toBe(true);
});
test("Object array", () => {
const result = algorithm.sort({
arr: objectArrData,
const result = algorithm.sort(objectArrData, {
func: (e) => e.num
});
expect(sortCheck(result.map(({ num }) => num))).toBe(true);
});
});
describe("Option test", () => {
test("Desc", () => {
const result = algorithm.sort({
arr: numArrData,
options: {
desc: true
}
const result = algorithm.sort(numArrData, {
desc: true
});
expect(sortCheck(result, true)).toBe(true);
});
Expand Down