In any application dealing with data, sorting is a fundamental operation. Whether it’s sorting user records by age, products by price, or any custom objects by specific attributes, a robust and flexible sorting function is invaluable. In this blog post, we’ll explore how to create a general-purpose sorting function in TypeScript. This function will handle sorting an array of objects by one or more attributes, each with optional order specifications (ascending or descending).
Simple Sorting by a Single Key
Let’s start with a simple scenario: sorting an array of objects by a single key. For instance, suppose we have an array of user objects, and we want to sort them by their age. Here’s a basic implementation:
/**
* Sorts an array of objects by a single key in ascending order.
*
* @param items The array of objects to sort.
* @param key The key to sort the objects by.
* @returns The sorted array.
*/
function sortBySingleKey(items: any[], key: string): any[] {
return items.sort((a, b) => {
const aval = a[key];
const bval = b[key];
if (aval < bval) {
return -1;
} else if (aval > bval) {
return 1;
}
return 0;
});
}
// Example usage:
const users = [
{ name: 'Alice', age: 25 },
{ name: 'Bob', age: 22 },
{ name: 'Charlie', age: 30 }
];
console.log(sortBySingleKey(users, 'age'));
This simple function sorts the array of users in ascending order by age. If the values are equal, the order remains unchanged.
Extending to Multiple Keys
Sorting by a single key is useful, but often, we need to sort by multiple keys. For example, we might want to sort users by age, and within users of the same age, sort by name. Here’s how we can extend our function to handle multiple keys:
/**
* Sorts an array of objects by multiple keys in ascending order.
*
* @param items The array of objects to sort.
* @param keys The keys to sort the objects by.
* @returns The sorted array.
*/
function sortByMultipleKeys(items: any[], ...keys: string[]): any[] {
return items.sort((a, b) => {
for (const key of keys) {
const aval = a[key];
const bval = b[key];
if (aval < bval) {
return -1;
} else if (aval > bval) {
return 1;
}
}
return 0;
});
}
// Example usage:
const users = [
{ name: 'Alice', age: 25 },
{ name: 'Bob', age: 25 },
{ name: 'Charlie', age: 22 }
];
console.log(sortByMultipleKeys(users, 'age', 'name'));
In this version, the function accepts a variable number of keys and sorts the array based on the order of the keys provided. This ensures a stable and predictable sort when multiple attributes are involved.
Adding Order Specification
The final enhancement is to allow each key to have an optional order argument, specifying whether the sort should be ascending or descending. We’ll define an enum for order directions and modify our function accordingly:
enum Order {
Asc = 'asc',
Desc = 'desc'
}
/**
* Sorts an array of objects by multiple keys, each with an optional order.
*
* @param items The array of objects to sort.
* @param attrs The keys to sort the objects by, each followed optionally by an order (Order.Asc or Order.Desc).
* @returns The sorted array.
*/
function sortByKeysWithOrder(items: any[], ...attrs: (string | Order)[]): any[] {
return items.sort((a, b) => {
for (let i = 0; i < attrs.length; i++) {
const key = attrs[i] as string;
let order: Order = Order.Asc;
if (i + 1 < attrs.length && (attrs[i + 1] === Order.Asc || attrs[i + 1] === Order.Desc)) {
order = attrs[i + 1] as Order;
i++;
}
const aval = a[key];
const bval = b[key];
if (aval < bval) {
return order === Order.Asc ? -1 : 1;
} else if (aval > bval) {
return order === Order.Asc ? 1 : -1;
}
}
return 0;
});
}
// Example usage:
const users = [
{ name: 'Alice', age: 25 },
{ name: 'Bob', age: 25 },
{ name: 'Charlie', age: 22 }
];
console.log(sortByKeysWithOrder(users, 'age', Order.Asc, 'name', Order.Desc));
Conclusion
In this article, we progressively built a versatile sorting function in TypeScript. Starting from a simple sort by a single key, we extended it to handle multiple keys and finally added support for specifying the order of each key. This general-purpose sorting function is now capable of handling complex sorting requirements, making it a valuable tool in your TypeScript arsenal.
By understanding and implementing these sorting techniques, you can efficiently manage and display your data in any application, providing both functionality and flexibility. Happy coding!
Comments are closed