https://github.com/wildhoney/setorder
Tiny module for sorting by a set order, using a custom sort function for omitting explicits.
https://github.com/wildhoney/setorder
exact-order explicit-order order ordering set-order specific-order
Last synced: 4 months ago
JSON representation
Tiny module for sorting by a set order, using a custom sort function for omitting explicits.
- Host: GitHub
- URL: https://github.com/wildhoney/setorder
- Owner: Wildhoney
- License: mit
- Created: 2017-04-03T18:37:26.000Z (about 9 years ago)
- Default Branch: master
- Last Pushed: 2017-12-06T10:04:56.000Z (over 8 years ago)
- Last Synced: 2024-12-31T09:42:07.368Z (over 1 year ago)
- Topics: exact-order, explicit-order, order, ordering, set-order, specific-order
- Language: JavaScript
- Homepage:
- Size: 95.7 KB
- Stars: 1
- Watchers: 3
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
- License: LICENSE
Awesome Lists containing this project
README
# Set Order
> Tiny module for sorting by a set order, using a custom sort function for omitting explicits.
> `npm i set-order --save`
> Useful for when you have an array of dynamic data, but you need to sort by a set order, rather than a natural sort order, such as alphabetically or numerically.




## Getting Started
Take a scenario where you have a list of bedroom counts where if the `count` is **zero** then it's labelled as **Studio** — those labelled as such should appear at the beginning of the array.
Using the native `sort` with a simple comparator function would yield an unsatisfactory result.
```javascript
const bedrooms = [4, 2, 'Studio', 1, 3];
bedrooms.sort((a, b) => a - b);
// [2, 4, 'Studio', 1, 3]
```
Instead by utilising `set-order` you're able to be explicit about which items should be grouped together in the sorting process, as well as where they reside in the array — at the beginning or at the end.
```javascript
import { exact } from 'set-order';
const bedrooms = [4, 2, 'Studio', 1, 3];
bedrooms.sort(exact(['Studio', 1, 2, 3, 4]));
// ['Studio', 1, 2, 3, 4]
```
### Sort
Taking the previous approach, its downside is immediately obvious in that you're required to specify **all** of the possible bedroom counts. Instead we'll specify **only** where **Studio** should appear since the other values can be numerically sorted using `a - b`.
```javascript
import { exact } from 'set-order';
const bedrooms = [4, 2, 'Studio', 1, 3];
bedrooms.sort(exact(['Studio'], (a, b) => a - b));
// ['Studio', 1, 2, 3, 4]
```
It's worth noting that if we didn't pass a comparator function that items that weren't mentioned explicitly will **not** be repositioned.
### Position
Building on the previous example we'll add an additional item entitled **etc...** which should appear at the end of the array: `['Studio', ..., 'etc...']` which we can easily achieve by using the `position` property that takes two possible values: `head` and `tail` where the default is `head`.
```javascript
import { exact, tail } from 'set-order';
const bedrooms = [4, 'etc...', 2, 'Studio', 1, 3];
bedrooms.sort(exact([
{ value: 'Studio' },
{ value: 'etc...', position: tail }
], (a, b) => a - b));
// ['Studio', 1, 2, 3, 4, 'etc...']
```
### Associative
Although the above is *almost* what we want, in real-life scenarios we're likely to be faced with an array of objects, rather than an array of primitives. For this `set-order` uses the fantastic [`object-path`](https://github.com/mariocasciaro/object-path) module which allows you to specify nested keys in the format `a.b.c` which would select `c` from `{ a: { b: { c: '!' }}}`.
```javascript
import { exact, tail } from 'set-order';
import by from 'sort-by';
const bedrooms = [
{ id: 1, bedrooms: 4 },
{ id: 2, bedrooms: 'etc...' },
{ id: 3, bedrooms: 2 },
{ id: 4, bedrooms: 'Studio' },
{ id: 5, bedrooms: 1 },
{ id: 6, bedrooms: 3 }
];
bedrooms.sort(exact([
{ property: 'bedrooms', value: 'Studio' },
{ property: 'bedrooms', value: 'etc...', position: tail }
], by('bedrooms')));
// [{ id: 4, bedrooms: 'Studio' }, { id: 5, bedrooms: 1' }] etc...
```
### Shorthand
Using the [associative](#Associative) approach we're successfully sorting an array of objects on the key `bedrooms`, but being explicit in saying that **Studio** should appear first — regardless of how many instances of **Studio** there may be in the array — and **etc...** should appear at the very end.
However memorising the `{ value, property, position }` interface may be somewhat difficult, nor is it too elegant. Instead we can be more succinct and chic by using `head` and `tail` as functions which take two parameters each: `value` and `property` where `property` is optional for an array of primitives.
```javascript
import { exact, head, tail } from 'set-order';
const bedrooms = [4, 'etc...', 2, 'Studio', 1, 3];
bedrooms.sort(exact([head('Studio'), tail('etc...')], (a, b) => a - b));
// ['Studio', 1, 2, 3, 4, 'etc...']
```