Skip to content

Instantly share code, notes, and snippets.

@kemsky

kemsky/sort.ts

Created Jan 21, 2017
Embed
What would you like to do?
Sort Example, TypeScript
export interface ISortOptions<T>
{
ignoreCase?:boolean;
projection?:(item:T) => any;
property?:string;
order?:boolean;
optimize?:boolean;
}
export function lense<T, U>(property:string):(item:T) => U
{
const path = property.split('.');
const p1:string = path.length > 0 ? path[0] : undefined;
const p2:string = path.length > 1 ? path[1] : undefined;
const p3:string = path.length > 2 ? path[2] : undefined;
const p4:string = path.length > 3 ? path[3] : undefined;
const p5:string = path.length > 4 ? path[4] : undefined;
switch(path.length)
{
case 1:
return (item:T):U =>
{
return item != null && p1 in item ? item[p1] : undefined;
};
case 2:
return (item:T):U =>
{
let result:U = undefined;
try
{
result = item[p1][p2];
}
catch(e)
{
}
return result;
};
case 3:
return (item:T):U =>
{
let result:U = undefined;
try
{
result = item[p1][p2][p3];
}
catch(e)
{
}
return result;
};
case 4:
return (item:T):U =>
{
let result:U = undefined;
try
{
result = item[p1][p2][p3][p4];
}
catch(e)
{
}
return result;
};
case 5:
return (item:T):U =>
{
let result:U = undefined;
try
{
result = item[p1][p2][p3][p4][p5];
}
catch(e)
{
}
return result;
};
}
throw new Error("Property is too deep: '" + name + "', maximum nesting is 5");
}
export function compare<T>(options:ISortOptions<T> = {}):(a:T, b:T) => number
{
const order:number = (options.order || options.order === undefined) ? 1 : -1;
let accessor:(item:T) => any;
if(typeof options.projection === 'function')
{
accessor = options.projection;
}
else if(typeof options.property === 'string')
{
accessor = lense<T, any>(options.property);
}
if(options.ignoreCase)
{
if(accessor != null)
{
return (a:T, b:T):number =>
{
const propertyA:any = accessor(a);
const propertyB:any = accessor(b);
const a1 = typeof propertyA === 'string' ? propertyA.toLocaleLowerCase() : propertyA;
const b1 = typeof propertyB === 'string' ? propertyB.toLocaleLowerCase() : propertyB;
if(a1 > b1)
{
return order;
}
if(a1 < b1)
{
return -order;
}
return 0;
};
}
return (a:T, b:T):number =>
{
const a1 = typeof a === 'string' ? (a as string).toLocaleLowerCase() : a;
const b1 = typeof b === 'string' ? (b as string).toLocaleLowerCase() : b;
if(a1 > b1)
{
return order;
}
if(a1 < b1)
{
return -order;
}
return 0;
};
}
if(accessor != null)
{
return (a:T, b:T):number =>
{
const a1 = accessor(a);
const b1 = accessor(b);
if(a1 > b1)
{
return order;
}
if(a1 < b1)
{
return -order;
}
return 0;
};
}
return order === 1 && options.optimize ? undefined : (a:T, b:T):number =>
{
if(a > b)
{
return order;
}
if(a < b)
{
return -order;
}
return 0;
};
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment