Sophisticated compare function for JavaScript ordering.
A commom problem in software development is defining a custom order for an object so that it can be compared to other objects of it's type (e.g. sorting an array of objects by a particular property).
Enter soph compare: an utility function that aims to reduce the need for complicated logic when defining an order over an object type by allowing you to specify the priority in which the properties should be checked, a direction (ascending / descending), a transform function (map a property) and a subConfig (configuration for nested objects) / compare function (user defined or returned by soph compare itself).
By allowing the configuration to receive a subConfig or a compare function you can define the order for an object, including its nested objects. If a subConfig property is provided then soph compare will recursively generate the compare function.
- Get the package from npm
npm install soph-compare
- Import it in your project
- require
const sophCompare = require('soph-compare');
- ES6 import
import * as sophCompare from 'soph-compare';
- Define a configuration object and call sophCompare to get the compare function
const config = [
{
prop: 'myProp',
descending: true,
},
{
prop: 'anotherProp',
},
];
const compare = sophCompare(config);
compare(arr1, arr2);
arr3.sort(compare);
function sophCompare(config?: OrderItem[]): (a, b) => number;
interface OrderItem {
prop?: string | number;
descending?: boolean;
transform?: (a) => any;
compare?: (a, b) => number;
subConfig?: sophCompare.OrderItem[];
}
The priority for evaluating each configuration item is defined by it's index from the configuration array, so order is important.
- Basic Usage
const arr = [
{
price: 32,
name: 'soy sauce packet',
},
{
price: 14,
name: 'avocado',
},
{
price: 14,
name: 'banana',
},
];
const config = [
{
prop: 'price',
},
{
prop: 'name',
},
];
expect(arr.sort(sophCompare(config))).toEqual([
{
price: 14,
name: 'avocado',
},
{
price: 14,
name: 'banana',
},
{
price: 32,
name: 'soy sauce packet',
},
]);
- descending
const arr = [
{
price: 32,
name: 'soy sauce packet',
},
{
price: 14,
name: 'bread',
},
{
price: 14,
name: 'avocado',
},
];
const config = [
{
prop: 'price',
},
{
prop: 'name',
descending: true,
},
];
expect(arr.sort(sophCompare(config))).toEqual([
{
price: 14,
name: 'bread',
},
{
price: 14,
name: 'avocado',
},
{
price: 32,
name: 'soy sauce packet',
},
]);
- transform
const arr = [
{
price: 32,
name: 'soy sauce packet',
},
{
price: 48,
name: 'bread',
},
{
price: 15,
name: 'avocado',
},
];
const config = [
{
prop: 'name',
transform: (a) => a.length,
},
{
prop: 'price',
},
];
expect(arr.sort(sophCompare(config))).toEqual([
{
price: 48,
name: 'bread',
},
{
price: 15,
name: 'avocado',
},
{
price: 32,
name: 'soy sauce packet',
},
]);
- subConfig
const arr = [
{
price: 32,
name: 'soy sauce packet',
vendors: {
count: 10,
location: 'RO',
},
},
{
price: 48,
name: 'bread',
vendors: {
count: 3,
location: 'UK',
},
},
{
price: 15,
name: 'avocado',
vendors: {
count: 15,
location: 'DE',
},
},
{
price: 8,
name: 'kiwi',
vendors: {
count: 15,
location: 'NZ',
},
},
];
const config = [
{
prop: 'vendors',
subConfig: [
{
prop: 'count',
},
{
prop: 'location',
descending: true,
},
],
},
{
prop: 'price',
},
{
prop: 'name',
},
];
expect(arr.sort(sophCompare(config))).toEqual([
{
price: 48,
name: 'bread',
vendors: {
count: 3,
location: 'UK',
},
},
{
price: 32,
name: 'soy sauce packet',
vendors: {
count: 10,
location: 'RO',
},
},
{
price: 8,
name: 'kiwi',
vendors: {
count: 15,
location: 'NZ',
},
},
{
price: 15,
name: 'avocado',
vendors: {
count: 15,
location: 'DE',
},
},
]);
- User defined compare
const arr = [
{
price: 32,
name: 'soy sauce packet',
vendors: {
count: 10,
location: 'RO',
},
},
{
price: 48,
name: 'bread',
vendors: {
count: 3,
location: 'UK',
},
},
{
price: 15,
name: 'avocado',
vendors: {
count: 15,
location: 'DE',
},
},
{
price: 8,
name: 'kiwi',
vendors: {
count: 15,
location: 'ES',
},
},
];
const config = [
{
prop: 'vendors',
compare: (a, b) => a.count - b.count,
},
{
prop: 'price',
},
{
prop: 'name',
},
];
expect(arr.sort(sophCompare(config))).toEqual([
{
price: 48,
name: 'bread',
vendors: {
count: 3,
location: 'UK',
},
},
{
price: 32,
name: 'soy sauce packet',
vendors: {
count: 10,
location: 'RO',
},
},
{
price: 8,
name: 'kiwi',
vendors: {
count: 15,
location: 'ES',
},
},
{
price: 15,
name: 'avocado',
vendors: {
count: 15,
location: 'DE',
},
},
]);
- compare returned by sophCompare
const arr = [
{
price: 32,
name: 'soy sauce packet',
vendors: {
count: 10,
location: 'RO',
},
},
{
price: 48,
name: 'bread',
vendors: {
count: 3,
location: 'UK',
},
},
{
price: 15,
name: 'avocado',
vendors: {
count: 15,
location: 'DE',
},
},
{
price: 8,
name: 'kiwi',
vendors: {
count: 15,
location: 'NZ',
},
},
];
const config = [
{
prop: 'vendors',
compare: sophCompare([
{
prop: 'count',
},
{
prop: 'location',
descending: true,
},
]),
},
{
prop: 'price',
},
{
prop: 'name',
},
];
expect(arr.sort(sophCompare(config))).toEqual([
{
price: 48,
name: 'bread',
vendors: {
count: 3,
location: 'UK',
},
},
{
price: 32,
name: 'soy sauce packet',
vendors: {
count: 10,
location: 'RO',
},
},
{
price: 8,
name: 'kiwi',
vendors: {
count: 15,
location: 'NZ',
},
},
{
price: 15,
name: 'avocado',
vendors: {
count: 15,
location: 'DE',
},
},
]);