@romanhavryliv/deep-sorting
Version:
Sorting function for arrays of objects.
140 lines (98 loc) • 4.55 kB
Markdown
# Deep Sorting
Sorting function for arrays of objects.
### install
```
npm install @romanhavryliv/deep-sorting
```
### usage
```
import deepSorting from '@romanhavryliv/deep-sorting';
...
deepSorting(arrayToSort, arrayOfSortingCriteria)
```
- `arrayToSort` - an array that needs to be sorted (is sorted **in place**).
- `arrayOfSortingCriteria` - an array of sorting criteria. Criteria can be a **string**, a **function** or an **array** of two elements where the first one is criteria itself (a **string** or a **function**) and the second one is **descendic pointer**. This "descendic pointer" points to sort the array by this particular criteria using descendic order. "Descendic" pointer should be only **"desc"** string. Any other value is ignored.
The _order_ of criteria in array is important for sorting order.
### examples
For example we have a database of pupils as an array of objects `pupils = [pupil1, pupil2, pupil3, ...]`.
And we have next structure of our objects (pupil1, pupil2, pupil3, ...):
```
{
name: {
firstName,
lastName,
},
marks: {
history, // e.g. [A, A, B, D, A],
arts, // e.g. [A, A, A],
},
}
```
_String_ sorting criteria is a path in pupil object to the primitive that must be compared for sorting. _String_ criteria can begin either with **"."** (period) or without it. `'.name.firstName'` and `'name.firstName'` are equal.
Also it can start with **"["** (opening square bracket)
```
`[${name}].firstName`
```
If we want to sort pupils by name we should write next `'.name.firstName'`.
And our `arrayOfSortingCriteria` would look like next
`arrayOfSortingCriteria = ['.name.firstName']`.
Or with descendic order:
`arrayOfSortingCriteria = [['.name.firstName', 'desc']]`.
_Function_ sorting criteria is a function that return some primitive that can be compared for sorting.
If we want to sort pupils by number of marks in History we should create next function
```
const historyMarksNumber = (pupil) => pupil.marks.history.length;
```
_or with descendic order:_
```
const historyMarksNumber = (pupil) => [pupil.marks.history.length, 'desc'];
```
and `arrayOfSortingCriteria = [historyMarksNumber]`.
### What is the purpose of **DEEP** sorting?
According to examples above we can combine those sorting methods.
If we pass next
`arrayOfSortingCriteria = ['.name.firstName', historyMarksNumber]` we can have such result as
| Name | History marks number |
| ---- | -------------------- |
| Adam | 8 |
| Adam | 7 |
| Adam | 5 |
| Bob | 7 |
| Eric | 8 |
Here we have three pupils with name _Adam_ and they are sorted by "History marks number" as well.
_Order of criteria in array is important for sorting order!_
For replaced criteria
`arrayOfSortingCriteria = [historyMarksNumber, '.name.firstName']` result is
| Name | History marks number |
| ---- | -------------------- |
| Adam | 8 |
| Eric | 8 |
| Adam | 7 |
| Bob | 7 |
| Adam | 5 |
Now we have two pupils with "History marks number" of "8" and two of "7" and they are sorted by "firstName" as well (_inside_ of mark "8" and "7").
Let's see the second table with _descendic_ order for the second criteria
`arrayOfSortingCriteria = [historyMarksNumber, ['.name.firstName', 'desc']]`:
| Name | History marks number |
| ---- | -------------------- |
| Eric | 8 |
| Adam | 8 |
| Bob | 7 |
| Adam | 7 |
| Adam | 5 |
Now we have descendic order of pupils by their firstName inside the list with the same "History marks number".
### Object complexity
The object (pupil) can be of any level of complexity combining objects and arrays inside.
Few more examples for _string_ criteria:
```
'.marks.arts[1]' - to sort pupils by "second mark of Arts".
`.marks[${subject}][1]` - to sort pupils by second mark of a "subject" passed as variable.
```
_Function_ complexity depends only on your needs.
The only thing it must do - _return a primitive_ for sorting comparison.
`arrayOfSortingCriteria` can contain only _strings_, only _functions_ or any _combination_ of those.
If an _empty array_ is passed as `arrayOfSortingCriteria` then regular sorting is applied (it doesn't change anything in array of objects).
### Change log (to v 1.1.x)
- fixed leading period issue
- added descentic order of sorting
- added typescript