Skip to content

Commit

Permalink
feat: Removed quicksort for stable sorting
Browse files Browse the repository at this point in the history
  • Loading branch information
iFaxity committed Jun 26, 2022
1 parent 672c28a commit 76119db
Show file tree
Hide file tree
Showing 9 changed files with 42 additions and 101 deletions.
8 changes: 4 additions & 4 deletions src/core/expression.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,19 +4,19 @@ import { createPredicate } from './expression';
describe.concurrent('#createPredicate()', () => {
it('test1', () => {
const expr = createPredicate<string>(null);
expect(expr()).toBeFalsy();
expect(expr('a')).toBeFalsy();
});
it('test2', () => {
const expr1 = createPredicate<string>(true);
expect(expr1()).toBeTruthy();
expect(expr1('a')).toBeTruthy();

const expr2 = createPredicate<string>(false);
expect(expr2()).toBeFalsy();
expect(expr2('a')).toBeFalsy();
});
it('test3', () => {
const expr1 = createPredicate<string>(() => true);
const expr2 = createPredicate(expr1);
expect(expr2()).toBeTruthy();
expect(expr2('a')).toBeTruthy();
});
});

Expand Down
6 changes: 3 additions & 3 deletions src/core/expression.ts
Original file line number Diff line number Diff line change
Expand Up @@ -60,9 +60,9 @@ function createExpression<T>(predicate: Predicate<T>): Expression<T> {
* @param expression - Default expression, could be a boolean indicating the default return value
* @returns The started expression
*/
export function createPredicate<T = any>(expression?: boolean): Expression<T>;
export function createPredicate<T = any>(expression?: Predicate<T>): Expression<T>;
export function createPredicate<T = any>(expression?: Predicate<T>|boolean): Expression<T> {
export function createPredicate<T>(expression?: boolean|null): Expression<T>;
export function createPredicate<T>(expression?: Predicate<T>): Expression<T>;
export function createPredicate<T>(expression?: Predicate<T>|boolean): Expression<T> {
let current = typeof expression == 'function'
? createExpression(expression)
: null;
Expand Down
1 change: 0 additions & 1 deletion src/core/index.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
export * from './enumerator';
export * from './expression';
export * from './quicksort';
export * from './types';
export * from './utils';
5 changes: 0 additions & 5 deletions src/core/quicksort.spec.ts

This file was deleted.

76 changes: 0 additions & 76 deletions src/core/quicksort.ts

This file was deleted.

2 changes: 1 addition & 1 deletion src/core/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ export type Operation<T = unknown, TRes = T> = Pipe<Enumerable<T>, Enumerable<TR
export type Collector<T = unknown, TRes = unknown> = Pipe<Enumerable<T>, TRes>;

export interface Predicate<T = unknown> {
(value?: T, index?: number): boolean
(value: T, index?: number): boolean
}

export type Accumulator<T, TAcc, TResult = unknown> = (acc: TAcc, value: T, index: number) => TResult;
Expand Down
31 changes: 27 additions & 4 deletions src/core/utils.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
import { quicksort } from './quicksort';
import { Comparison, Enumerable, Grouping, OrderedEnumerable, Pipe, Key } from './types';

/**
Expand Down Expand Up @@ -31,6 +30,30 @@ export function deepEqual<
return (Object.keys(b).length == keys.length) && keys.every(key => deepEqual(a[key], b[key]));
}

/**
* Shim to ensure stable sorting in pre ES2019 browser engines, as sorting is unstable
* @param source - Input iterable to sort
* @param comparisons - Array of comparison functions to use in the sorting, at least one is required
* @returns A copy of the array, but sorted
* @internal
*/
function stableSort<T>(source: Enumerable<T>, comparers: Comparison<T>[]): T[] {
// Sort with comparer functions chained into each other if the previous one returns 0
const list = [ ...source ];

return list.sort((x, y) => {
for (let idx = 0; idx < comparers.length; idx++) {
const res = comparers[idx](x, y);

if (res !== 0) {
return res;
}
}

return list.indexOf(x) - list.indexOf(y);
});
}

/**
*
* @param source
Expand All @@ -45,9 +68,9 @@ export function createOrderedEnumerable<T>(comparer: Comparison<T>): Pipe<Enumer
return Object.create({
comparers,
[Symbol.iterator]() {
const sorter = quicksort(source, ...comparers);
return sorter[Symbol.iterator]();
const sorted = stableSort(source, comparers);

return sorted[Symbol.iterator]();
},
});
};
Expand Down
12 changes: 6 additions & 6 deletions src/order/__snapshots__/orderByDescending.spec.ts.snap
Original file line number Diff line number Diff line change
Expand Up @@ -2,18 +2,18 @@

exports[`#orderByDescending() > test1 1`] = `
[
{
"carbs": 49,
"fat": 16,
"name": "Gingerbread",
"prot": 0,
},
{
"carbs": 24,
"fat": 16,
"name": "Eclair",
"prot": 6,
},
{
"carbs": 49,
"fat": 16,
"name": "Gingerbread",
"prot": 0,
},
{
"carbs": 37,
"fat": 9,
Expand Down
2 changes: 1 addition & 1 deletion vite.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ export default defineConfig({
entry: resolve(__dirname, './src/index.ts'),
formats: [ 'cjs', 'es' ],
name: 'interlinqed',
fileName: (format) => `index.${format}.js`
fileName: (format) => `index.${format}.js`,
},
},
});

0 comments on commit 76119db

Please sign in to comment.