@@ -142,9 +142,13 @@ export const functions: FunctionBuildersMap = {
142
142
const sign = direction === 'desc' ? -1 : 1
143
143
144
144
function compare(itemA: unknown, itemB: unknown) {
145
-
const a = getter(itemA)
146
-
const b = getter(itemB)
147
-
return gt(a, b) ? sign : lt(a, b) ? -sign : 0
145
+
try {
146
+
const a = getter(itemA)
147
+
const b = getter(itemB)
148
+
return gt(a, b) ? sign : lt(a, b) ? -sign : 0
149
+
} catch {
150
+
return 0 // leave unsortable contents as-is
151
+
}
148
152
}
149
153
150
154
return (data: T[]) => data.slice().sort(compare)
@@ -258,21 +262,16 @@ export const functions: FunctionBuildersMap = {
258
262
data.length,
259
263
260
264
keys: () => Object.keys,
261
-
262
265
values: () => Object.values,
263
266
264
-
prod: () => (data: number[]) => data.reduce((a, b) => a * b),
265
-
266
-
sum: () => (data: number[]) => data.reduce((a, b) => a + b),
267
-
268
-
average: () => (data: number[]) => (functions.sum()(data) as number) / data.length,
267
+
prod: () => (data: number[]) => reduce(data, (a, b) => a * b),
268
+
sum: () => (data: number[]) => reduce(data, (a, b) => a + b, 0),
269
+
average: () => (data: number[]) => reduce(data, (a, b) => a + b) / data.length,
270
+
min: () => (data: number[]) => reduce(data, (a, b) => Math.min(a, b), null),
271
+
max: () => (data: number[]) => reduce(data, (a, b) => Math.max(a, b), null),
269
272
270
-
min: () => (data: number[]) => Math.min(...data),
271
-
272
-
max: () => (data: number[]) => Math.max(...data),
273
-
274
-
and: buildFunction((...args) => args.reduce((a, b) => !!(a && b))),
275
-
or: buildFunction((...args) => args.reduce((a, b) => !!(a || b))),
273
+
and: buildFunction((...args: unknown[]) => reduce(args, (a, b) => !!(a && b))),
274
+
or: buildFunction((...args: unknown[]) => reduce(args, (a, b) => !!(a || b))),
276
275
not: buildFunction((a: unknown) => !a),
277
276
278
277
exists: (queryGet: JSONQueryFunction) => {
@@ -343,3 +342,27 @@ export const functions: FunctionBuildersMap = {
343
342
}
344
343
345
344
const truthy = (x: unknown) => x !== null && x !== 0 && x !== false
345
+
346
+
const reduce = <T>(
347
+
data: T[],
348
+
callback: (previousValue: T, currentValue: T) => T,
349
+
initialValue?: T
350
+
): T => {
351
+
if (!isArray(data)) {
352
+
throwTypeError('Array expected')
353
+
}
354
+
355
+
if (initialValue !== undefined) {
356
+
return data.reduce(callback, initialValue)
357
+
}
358
+
359
+
if (data.length === 0) {
360
+
throwTypeError('Non-empty array expected')
361
+
}
362
+
363
+
return data.reduce(callback)
364
+
}
365
+
366
+
export const throwTypeError = (message: string) => {
367
+
throw new TypeError(message)
368
+
}
RetroSearch is an open source project built by @garambo | Open a GitHub Issue
Search and Browse the WWW like it's 1997 | Search results from DuckDuckGo
HTML:
3.2
| Encoding:
UTF-8
| Version:
0.7.4