Skip to content

Commit 3a6e9c9

Browse files
author
bjvickers
committed
feat: add support for descending sort
Rewrite tests to support new api and first draft of api. fixes issue #6
1 parent aedc7c0 commit 3a6e9c9

File tree

7 files changed

+1838
-220
lines changed

7 files changed

+1838
-220
lines changed

index.js

Lines changed: 92 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
const arrayify = require('array-back')
12
const t = require('typical')
23

34
/**
@@ -89,17 +90,63 @@ module.exports = sortBy
8990
* }
9091
* ```
9192
*/
92-
function sortBy (recordset, sortBy, computedProperties) {
93-
return recordset.sort(compare(sortBy, computedProperties))
93+
// @TODO: Incorporate sharedCompProps into sanity checks
94+
function sortBy (recordset, sortBy, sortTypes, sharedCompProps) {
95+
// Ensure arguments are of the expected type
96+
recordset = arrayify(recordset)
97+
sortBy = arrayify(sortBy)
98+
sortTypes = arrayify(sortTypes)
99+
100+
// Perform sanity checks early.
101+
let isPrimitiveSort = recordset.some(record => t.isPrimitive(record))
102+
if (isPrimitiveSort) {
103+
// Any 'sortBy' arguments invalidate the sort, because they will not be
104+
// applicable on a primitive array.
105+
if (sortBy.length !== 0) {
106+
return recordset
107+
}
108+
} else {
109+
// At least one 'sortBy' argument must be provided, so that the recordset
110+
// can be sorted according to that property.
111+
if (sortBy.length === 0) {
112+
return recordset
113+
}
114+
}
115+
116+
// Ensure the arguments are correctly provided. Hydrate or prune as
117+
// required.
118+
if ((sortBy.length === 0) && (sortTypes.length === 0)) {
119+
sortTypes.push('asc')
120+
} else if (sortBy.length > sortTypes.length) {
121+
// Not enough sortTypes have been provided. Fully hydrate the sortTypes
122+
// array, using 'asc' by default.
123+
let noOfMissingSortTypes = sortBy.length - sortTypes.length
124+
for (let i = 0; i < noOfMissingSortTypes; i++) {
125+
sortTypes.push('asc')
126+
}
127+
} else if (sortBy.length < sortTypes.length) {
128+
// Too many sortTypes have been provided. Prune the redundant ones
129+
// at the end of the sortType array.
130+
sortTypes.splice(-1, noOfExcessSortTypes)
131+
}
132+
133+
if (isPrimitiveSort) {
134+
return recordset.sort(comparePrim(sortBy, sortTypes))
135+
} else {
136+
return recordset.sort(compare(sortBy, sortTypes, sharedCompProps))
137+
}
138+
}
139+
140+
function comparePrim (sortBy, sortTypes) {
141+
console.log('comparePrim() NOT YET IMPLEMENTED')
94142
}
95143

96-
// @TODO: Question - do we support crap data in? E.g. testing for 't.isArrayLike',
97-
// @TODO: rather than just assuming the data in is correct?
98-
function compare (sortBy, computedProperties) {
99-
let sorts = Object.entries(sortBy)
100-
let propSort = sorts.shift()
101-
let property = t.isArrayLike(propSort) && propSort[0] || undefined
102-
let sort = t.isArrayLike(propSort) && propSort[1] || 'asc'
144+
function compare (sortBy, sortTypes, sharedCompProps) {
145+
let sorts = sortBy.slice(0)
146+
let property = sorts.shift()
147+
148+
let types = sortTypes.slice(0)
149+
let sort = types.shift()
103150

104151
return function sorter (a, b) {
105152
let x
@@ -108,47 +155,40 @@ function compare (sortBy, computedProperties) {
108155
let recurse
109156
let currentSort = sort
110157

111-
if (t.isDefined(computedProperties) && computedProperties.hasOwnProperty(property)) {
112-
x = computedProperties[property](a)
113-
y = computedProperties[property](b)
114-
} else {
158+
if (t.isFunction(sort)) {
159+
// Apply a calculated property sort
160+
x = sort(a)
161+
y = sort(b)
162+
// Perform an asc sort by default, then invert later if a desc has been
163+
// requested for the current property.
164+
results = getAscOrder(x, y)
165+
} else if (t.isArrayLike(sort)) {
166+
// Apply custom ordering
115167
x = a[property]
116168
y = b[property]
117-
}
118-
119-
if (t.isArrayLike(sort)) {
120-
// Custom sort the current property.
121169
result = sort.indexOf(y) - sort.indexOf(x)
122170
} else {
123-
// Asc/desc sort the current property. Perform an asc sort by default,
124-
// then invert the result later if a desc has been requested for the
125-
// current property.
126-
if (x === null && y === null) {
127-
result = 0
128-
} else if ((!t.isDefined(x) || x === null) && t.isDefined(y)) {
129-
result = -1
130-
} else if (t.isDefined(x) && (!t.isDefined(y) || y === null)) {
131-
result = 1
132-
} else if (!t.isDefined(x) && !t.isDefined(y)) {
133-
result = 0
134-
} else {
135-
result = x < y ? -1 : x > y ? 1 : 0
136-
}
171+
// Apply a simple asc/desc sort
172+
x = a[property]
173+
y = b[property]
174+
// Perform an asc sort by default, then invert later if a desc has been
175+
// requested for the current property.
176+
results = getAscOrder(x, y)
137177
}
138178

139-
// Reset this sorting function and parent, unless we have an equal
179+
// Reset this sorting function and parent, unless there is an equal
140180
// result and there are more sorts still to perform, in which case
141181
// move on to the next one.
142182
if (result === 0 && sorts.length) {
143183
recurse = true
144184
} else {
145185
recurse = false
146-
sorts = Object.entries(sortBy)
186+
sorts = sortBy.slice(0)
187+
types = sortTypes.slice(0)
147188
}
148189

149-
propSort = sorts.shift()
150-
property = t.isArrayLike(propSort) && propSort[0] || undefined
151-
sort = t.isArrayLike(propSort) && propSort[1] || 'asc'
190+
property = sorts.shift()
191+
sort = types.shift()
152192

153193
// Present the result
154194
if (recurse) {
@@ -160,3 +200,19 @@ function compare (sortBy, computedProperties) {
160200
}
161201
}
162202
}
203+
204+
function getAscOrder(x, y) {
205+
let result
206+
if (x === null && y === null) {
207+
result = 0
208+
} else if ((!t.isDefined(x) || x === null) && t.isDefined(y)) {
209+
result = -1
210+
} else if (t.isDefined(x) && (!t.isDefined(y) || y === null)) {
211+
result = 1
212+
} else if (!t.isDefined(x) && !t.isDefined(y)) {
213+
result = 0
214+
} else {
215+
result = x < y ? -1 : x > y ? 1 : 0
216+
}
217+
return result
218+
}

0 commit comments

Comments
 (0)