{"id":15890570,"url":"https://github.com/dimfeld/sorters","last_synced_at":"2025-03-20T11:36:11.123Z","repository":{"id":57366389,"uuid":"279012788","full_name":"dimfeld/sorters","owner":"dimfeld","description":"Sort an array considering multiple fields and sort orders.","archived":false,"fork":false,"pushed_at":"2022-10-14T08:00:00.000Z","size":48,"stargazers_count":4,"open_issues_count":0,"forks_count":1,"subscribers_count":2,"default_branch":"master","last_synced_at":"2025-03-01T00:07:11.627Z","etag":null,"topics":["sort"],"latest_commit_sha":null,"homepage":"","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/dimfeld.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2020-07-12T07:17:15.000Z","updated_at":"2022-09-27T19:14:44.000Z","dependencies_parsed_at":"2022-08-23T20:10:40.944Z","dependency_job_id":null,"html_url":"https://github.com/dimfeld/sorters","commit_stats":null,"previous_names":[],"tags_count":6,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dimfeld%2Fsorters","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dimfeld%2Fsorters/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dimfeld%2Fsorters/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dimfeld%2Fsorters/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/dimfeld","download_url":"https://codeload.github.com/dimfeld/sorters/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":244068860,"owners_count":20392907,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["sort"],"created_at":"2024-10-06T07:06:48.254Z","updated_at":"2025-03-20T11:36:10.820Z","avatar_url":"https://github.com/dimfeld.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"Sorters is a compact package for generating Javascript array `sort` comparators that handle things like null values, descending sort, and multi-level comparisons.\n\n# Usage\n\nThe `sorter` function builds and returns a comparator function that uses the specified comparison order. This returned function can be used with  `Array.sort` or just to order any two objects.\n\n```js\nimport { sorter } from 'sorters';\n\nlet data = [\n  { a: 5, b: 'strb', c: new Date('2017-06-01') },\n  { a: 2, b: 'stra', c: new Date('2018-05-01') },\n  { a: null, b: null },\n  { a: 2, b: 'strc', c: new Date('2018-02-01') },\n];\n\n// Sort first on `c`, counting nullish values as higher than the others.\n// If `c` is equal on two objects, use `a` in ascending order, and if `a` is equal then sort by\n// `b` in descending order.\ndata.sort(sorter(\n    { value: 'c', nulls: Nulls.High },\n    'a',\n    { value: (val) =\u003e val.b, descending: true, type: ValueType.String }\n  ));\n  \n\n// Result: \n[\n  { a: 5, b: 'strb', c: 2017-06-01T00:00:00.000Z },\n  { a: 2, b: 'strc', c: 2018-02-01T00:00:00.000Z },\n  { a: 2, b: 'stra', c: 2018-05-01T00:00:00.000Z },\n  { a: null, b: null }\n]\n```\n\n## Examples\n\n\nSort by the value of the `a` field in ascending order.\n```js\n\n\u003e data.sort(sorter('a'))\n[\n  { a: null, b: null },\n  { a: 2, b: 'strc', c: 2018-02-01T00:00:00.000Z },\n  { a: 2, b: 'stra', c: 2018-05-01T00:00:00.000Z },\n  { a: 5, b: 'strb', c: 2017-06-01T00:00:00.000Z }\n]\n```\n\nSort by the value of the `a` field in descending order.\n```js\n\u003e data.sort(sorter({ value: 'a', descending: true }));\n[\n  { a: 5, b: 'strb', c: 2017-06-01T00:00:00.000Z },\n  { a: 2, b: 'strc', c: 2018-02-01T00:00:00.000Z },\n  { a: 2, b: 'stra', c: 2018-05-01T00:00:00.000Z },\n  { a: null, b: null }\n]\n```\n\nSort by the month value of the `c` field.\n```js\n// Note the `?.` operator to handle when `c` is missing.\n\u003e data.sort(sorter((obj) =\u003e obj.c?.getUTCMonth()));\n[\n  { a: null, b: null },\n  { a: 2, b: 'strc', c: 2018-02-01T00:00:00.000Z },\n  { a: 2, b: 'stra', c: 2018-05-01T00:00:00.000Z },\n  { a: 5, b: 'strb', c: 2017-06-01T00:00:00.000Z }\n]\n```\n\nSort by the `a` field, and when comparing objects with the same value for `a`, compare `b` instead.\n```js\n\u003e data.sort(sorter('a', 'b'));\n[\n  { a: null, b: null },\n  { a: 2, b: 'stra', c: 2018-05-01T00:00:00.000Z },\n  { a: 2, b: 'strc', c: 2018-02-01T00:00:00.000Z },\n  { a: 5, b: 'strb', c: 2017-06-01T00:00:00.000Z }\n]\n```\n\nSame, but when comparing `b` use descending order.\n```js\n\u003e data.sort(sorter('a', { value: 'b', descending: true }));\n[\n  { a: null, b: null },\n  { a: 2, b: 'strc', c: 2018-02-01T00:00:00.000Z },\n  { a: 2, b: 'stra', c: 2018-05-01T00:00:00.000Z },\n  { a: 5, b: 'strb', c: 2017-06-01T00:00:00.000Z }\n]\n```\n\nSort by `a` ascending, and counting nullish values as higher than the others.\n```js\n\u003e data.sort(sorter({ value: 'a', nulls: Nulls.High /* or just 'high` if not using Typescript */))\n[\n  { a: 2, b: 'strc', c: 2018-02-01T00:00:00.000Z },\n  { a: 2, b: 'stra', c: 2018-05-01T00:00:00.000Z },\n  { a: 5, b: 'strb', c: 2017-06-01T00:00:00.000Z },\n  { a: null, b: null }\n]\n```\n\n## Arguments\n\nEach argument to the `sorter` function is an object that represents how to perform a single level of the sort.\n\nIf two items in the array are equal for a particular level, then the next level is tried, and so on until a difference is found or all levels have equal values.\n\nThe object contains four properties:\n\n### value\n\n`value` specifies which field to access in each item. It can be a function, a string specifying a path, or an array specifying a path.\n\nWhen `value` is the only argument required, it can also be passed directly as the argument instead of wrapping it with an object, as in the `'a'` argument in the example above.\n\n### descending\n\n`descending` is an optional boolean indicating that the sort should be done in descending order. If omitted, the sort is done in ascending order.\n\n### type\n\n`type` gives the sorter a hint as the to type of data it will encounter. Typescript users can use the `ValueType` enum, and others can use the values `string`, `number`, and `date`.\n\nIf some of the data does not match the specified type, you will likely encounter incorrect results or an error.\n\nThe default value is `any`, which will detect the type of value as it is sorted and act appropriately.\n\n```typescript\nexport enum ValueType {\n  Any = 'any',\n  String = 'string',\n  Number = 'number',\n  Date = 'date',\n}\n```\n\n### nulls\n\nHow to treat null or undefined values in the data. Typescript users can use the `Nulls` enum, while others can use the values `low`, `high`, and `none`.\n\n```typescript\nexport enum Nulls {\n  /** Treat nulls as lower than any other values. This is the default setting. */\n  Low = 'low',\n  /** Treat nulls as higher than any other values. */\n  High = 'high',\n  /** Assume there are no nullish values in the data. This may cause exceptions if you are wrong. */\n  None = 'none',\n}\n```\n\nUsing `Nulls.None` in data that contains nullish values will probably cause an error.\n\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdimfeld%2Fsorters","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fdimfeld%2Fsorters","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdimfeld%2Fsorters/lists"}