@dxyl/utils 1.1.2 → 1.1.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/_30s.js +1931 -0
- package/package.json +7 -1
package/lib/_30s.js
ADDED
|
@@ -0,0 +1,1931 @@
|
|
|
1
|
+
|
|
2
|
+
const fs = typeof require !== "undefined" && require('fs');
|
|
3
|
+
const crypto = typeof require !== "undefined" && require('crypto');
|
|
4
|
+
|
|
5
|
+
const all = (arr, fn = Boolean) => arr.every(fn);
|
|
6
|
+
const allEqual = arr => arr.every(val => val === arr[0]);
|
|
7
|
+
const any = (arr, fn = Boolean) => arr.some(fn);
|
|
8
|
+
const approximatelyEqual = (v1, v2, epsilon = 0.001) => Math.abs(v1 - v2) < epsilon;
|
|
9
|
+
const arrayToCSV = (arr, delimiter = ',') =>
|
|
10
|
+
arr
|
|
11
|
+
.map(v => v.map(x => (isNaN(x) ? `"${x.replace(/"/g, '""')}"` : x)).join(delimiter))
|
|
12
|
+
.join('\n');
|
|
13
|
+
const arrayToHtmlList = (arr, listID) =>
|
|
14
|
+
(el => (
|
|
15
|
+
(el = document.querySelector('#' + listID)),
|
|
16
|
+
(el.innerHTML += arr.map(item => `<li>${item}</li>`).join(''))
|
|
17
|
+
))();
|
|
18
|
+
const ary = (fn, n) => (...args) => fn(...args.slice(0, n));
|
|
19
|
+
const atob = str => Buffer.from(str, 'base64').toString('binary');
|
|
20
|
+
const attempt = (fn, ...args) => {
|
|
21
|
+
try {
|
|
22
|
+
return fn(...args);
|
|
23
|
+
} catch (e) {
|
|
24
|
+
return e instanceof Error ? e : new Error(e);
|
|
25
|
+
}
|
|
26
|
+
};
|
|
27
|
+
const average = (...nums) => nums.reduce((acc, val) => acc + val, 0) / nums.length;
|
|
28
|
+
const averageBy = (arr, fn) =>
|
|
29
|
+
arr.map(typeof fn === 'function' ? fn : val => val[fn]).reduce((acc, val) => acc + val, 0) /
|
|
30
|
+
arr.length;
|
|
31
|
+
const bifurcate = (arr, filter) =>
|
|
32
|
+
arr.reduce((acc, val, i) => (acc[filter[i] ? 0 : 1].push(val), acc), [[], []]);
|
|
33
|
+
const bifurcateBy = (arr, fn) =>
|
|
34
|
+
arr.reduce((acc, val, i) => (acc[fn(val, i) ? 0 : 1].push(val), acc), [[], []]);
|
|
35
|
+
const bind = (fn, context, ...boundArgs) => (...args) => fn.apply(context, [...boundArgs, ...args]);
|
|
36
|
+
const bindAll = (obj, ...fns) =>
|
|
37
|
+
fns.forEach(
|
|
38
|
+
fn => (
|
|
39
|
+
(f = obj[fn]),
|
|
40
|
+
(obj[fn] = function() {
|
|
41
|
+
return f.apply(obj);
|
|
42
|
+
})
|
|
43
|
+
)
|
|
44
|
+
);
|
|
45
|
+
const bindKey = (context, fn, ...boundArgs) => (...args) =>
|
|
46
|
+
context[fn].apply(context, [...boundArgs, ...args]);
|
|
47
|
+
const binomialCoefficient = (n, k) => {
|
|
48
|
+
if (Number.isNaN(n) || Number.isNaN(k)) return NaN;
|
|
49
|
+
if (k < 0 || k > n) return 0;
|
|
50
|
+
if (k === 0 || k === n) return 1;
|
|
51
|
+
if (k === 1 || k === n - 1) return n;
|
|
52
|
+
if (n - k < k) k = n - k;
|
|
53
|
+
let res = n;
|
|
54
|
+
for (let j = 2; j <= k; j++) res *= (n - j + 1) / j;
|
|
55
|
+
return Math.round(res);
|
|
56
|
+
};
|
|
57
|
+
const bottomVisible = () =>
|
|
58
|
+
document.documentElement.clientHeight + window.scrollY >=
|
|
59
|
+
(document.documentElement.scrollHeight || document.documentElement.clientHeight);
|
|
60
|
+
const btoa = str => Buffer.from(str, 'binary').toString('base64');
|
|
61
|
+
const byteSize = str => new Blob([str]).size;
|
|
62
|
+
const call = (key, ...args) => context => context[key](...args);
|
|
63
|
+
const capitalize = ([first, ...rest], lowerRest = false) =>
|
|
64
|
+
first.toUpperCase() + (lowerRest ? rest.join('').toLowerCase() : rest.join(''));
|
|
65
|
+
const capitalizeEveryWord = str => str.replace(/\b[a-z]/g, char => char.toUpperCase());
|
|
66
|
+
const castArray = val => (Array.isArray(val) ? val : [val]);
|
|
67
|
+
const chainAsync = fns => {
|
|
68
|
+
let curr = 0;
|
|
69
|
+
const last = fns[fns.length - 1];
|
|
70
|
+
const next = () => {
|
|
71
|
+
const fn = fns[curr++];
|
|
72
|
+
fn === last ? fn() : fn(next);
|
|
73
|
+
};
|
|
74
|
+
next();
|
|
75
|
+
};
|
|
76
|
+
const checkProp = (predicate, prop) => obj => !!predicate(obj[prop]);
|
|
77
|
+
const chunk = (arr, size) =>
|
|
78
|
+
Array.from({ length: Math.ceil(arr.length / size) }, (v, i) =>
|
|
79
|
+
arr.slice(i * size, i * size + size)
|
|
80
|
+
);
|
|
81
|
+
const clampNumber = (num, a, b) => Math.max(Math.min(num, Math.max(a, b)), Math.min(a, b));
|
|
82
|
+
const cloneRegExp = regExp => new RegExp(regExp.source, regExp.flags);
|
|
83
|
+
const coalesce = (...args) => args.find(_ => ![undefined, null].includes(_));
|
|
84
|
+
const coalesceFactory = valid => (...args) => args.find(valid);
|
|
85
|
+
const collectInto = fn => (...args) => fn(args);
|
|
86
|
+
const colorize = (...args) => ({
|
|
87
|
+
black: `\x1b[30m${args.join(' ')}`,
|
|
88
|
+
red: `\x1b[31m${args.join(' ')}`,
|
|
89
|
+
green: `\x1b[32m${args.join(' ')}`,
|
|
90
|
+
yellow: `\x1b[33m${args.join(' ')}`,
|
|
91
|
+
blue: `\x1b[34m${args.join(' ')}`,
|
|
92
|
+
magenta: `\x1b[35m${args.join(' ')}`,
|
|
93
|
+
cyan: `\x1b[36m${args.join(' ')}`,
|
|
94
|
+
white: `\x1b[37m${args.join(' ')}`,
|
|
95
|
+
bgBlack: `\x1b[40m${args.join(' ')}\x1b[0m`,
|
|
96
|
+
bgRed: `\x1b[41m${args.join(' ')}\x1b[0m`,
|
|
97
|
+
bgGreen: `\x1b[42m${args.join(' ')}\x1b[0m`,
|
|
98
|
+
bgYellow: `\x1b[43m${args.join(' ')}\x1b[0m`,
|
|
99
|
+
bgBlue: `\x1b[44m${args.join(' ')}\x1b[0m`,
|
|
100
|
+
bgMagenta: `\x1b[45m${args.join(' ')}\x1b[0m`,
|
|
101
|
+
bgCyan: `\x1b[46m${args.join(' ')}\x1b[0m`,
|
|
102
|
+
bgWhite: `\x1b[47m${args.join(' ')}\x1b[0m`
|
|
103
|
+
});
|
|
104
|
+
const compact = arr => arr.filter(Boolean);
|
|
105
|
+
const compactWhitespace = str => str.replace(/\s{2,}/g, ' ');
|
|
106
|
+
const compose = (...fns) => fns.reduce((f, g) => (...args) => f(g(...args)));
|
|
107
|
+
const composeRight = (...fns) => fns.reduce((f, g) => (...args) => g(f(...args)));
|
|
108
|
+
const converge = (converger, fns) => (...args) => converger(...fns.map(fn => fn.apply(null, args)));
|
|
109
|
+
const copyToClipboard = str => {
|
|
110
|
+
const el = document.createElement('textarea');
|
|
111
|
+
el.value = str;
|
|
112
|
+
el.setAttribute('readonly', '');
|
|
113
|
+
el.style.position = 'absolute';
|
|
114
|
+
el.style.left = '-9999px';
|
|
115
|
+
document.body.appendChild(el);
|
|
116
|
+
const selected =
|
|
117
|
+
document.getSelection().rangeCount > 0 ? document.getSelection().getRangeAt(0) : false;
|
|
118
|
+
el.select();
|
|
119
|
+
document.execCommand('copy');
|
|
120
|
+
document.body.removeChild(el);
|
|
121
|
+
if (selected) {
|
|
122
|
+
document.getSelection().removeAllRanges();
|
|
123
|
+
document.getSelection().addRange(selected);
|
|
124
|
+
}
|
|
125
|
+
};
|
|
126
|
+
const countBy = (arr, fn) =>
|
|
127
|
+
arr.map(typeof fn === 'function' ? fn : val => val[fn]).reduce((acc, val) => {
|
|
128
|
+
acc[val] = (acc[val] || 0) + 1;
|
|
129
|
+
return acc;
|
|
130
|
+
}, {});
|
|
131
|
+
const counter = (selector, start, end, step = 1, duration = 2000) => {
|
|
132
|
+
let current = start,
|
|
133
|
+
_step = (end - start) * step < 0 ? -step : step,
|
|
134
|
+
timer = setInterval(() => {
|
|
135
|
+
current += _step;
|
|
136
|
+
document.querySelector(selector).innerHTML = current;
|
|
137
|
+
if (current >= end) document.querySelector(selector).innerHTML = end;
|
|
138
|
+
if (current >= end) clearInterval(timer);
|
|
139
|
+
}, Math.abs(Math.floor(duration / (end - start))));
|
|
140
|
+
return timer;
|
|
141
|
+
};
|
|
142
|
+
const countOccurrences = (arr, val) => arr.reduce((a, v) => (v === val ? a + 1 : a), 0);
|
|
143
|
+
const createDirIfNotExists = dir => (!fs.existsSync(dir) ? fs.mkdirSync(dir) : undefined);
|
|
144
|
+
const createElement = str => {
|
|
145
|
+
const el = document.createElement('div');
|
|
146
|
+
el.innerHTML = str;
|
|
147
|
+
return el.firstElementChild;
|
|
148
|
+
};
|
|
149
|
+
const createEventHub = () => ({
|
|
150
|
+
hub: Object.create(null),
|
|
151
|
+
emit(event, data) {
|
|
152
|
+
(this.hub[event] || []).forEach(handler => handler(data));
|
|
153
|
+
},
|
|
154
|
+
on(event, handler) {
|
|
155
|
+
if (!this.hub[event]) this.hub[event] = [];
|
|
156
|
+
this.hub[event].push(handler);
|
|
157
|
+
},
|
|
158
|
+
off(event, handler) {
|
|
159
|
+
const i = (this.hub[event] || []).findIndex(h => h === handler);
|
|
160
|
+
if (i > -1) this.hub[event].splice(i, 1);
|
|
161
|
+
if (this.hub[event].length === 0) delete this.hub[event];
|
|
162
|
+
}
|
|
163
|
+
});
|
|
164
|
+
const CSVToArray = (data, delimiter = ',', omitFirstRow = false) =>
|
|
165
|
+
data
|
|
166
|
+
.slice(omitFirstRow ? data.indexOf('\n') + 1 : 0)
|
|
167
|
+
.split('\n')
|
|
168
|
+
.map(v => v.split(delimiter));
|
|
169
|
+
const CSVToJSON = (data, delimiter = ',') => {
|
|
170
|
+
const titles = data.slice(0, data.indexOf('\n')).split(delimiter);
|
|
171
|
+
return data
|
|
172
|
+
.slice(data.indexOf('\n') + 1)
|
|
173
|
+
.split('\n')
|
|
174
|
+
.map(v => {
|
|
175
|
+
const values = v.split(delimiter);
|
|
176
|
+
return titles.reduce((obj, title, index) => ((obj[title] = values[index]), obj), {});
|
|
177
|
+
});
|
|
178
|
+
};
|
|
179
|
+
const currentURL = () => window.location.href;
|
|
180
|
+
const curry = (fn, arity = fn.length, ...args) =>
|
|
181
|
+
arity <= args.length ? fn(...args) : curry.bind(null, fn, arity, ...args);
|
|
182
|
+
const dayOfYear = date =>
|
|
183
|
+
Math.floor((date - new Date(date.getFullYear(), 0, 0)) / 1000 / 60 / 60 / 24);
|
|
184
|
+
const debounce = (fn, ms = 0) => {
|
|
185
|
+
let timeoutId;
|
|
186
|
+
return function(...args) {
|
|
187
|
+
clearTimeout(timeoutId);
|
|
188
|
+
timeoutId = setTimeout(() => fn.apply(this, args), ms);
|
|
189
|
+
};
|
|
190
|
+
};
|
|
191
|
+
const decapitalize = ([first, ...rest], upperRest = false) =>
|
|
192
|
+
first.toLowerCase() + (upperRest ? rest.join('').toUpperCase() : rest.join(''));
|
|
193
|
+
const deepClone = obj => {
|
|
194
|
+
let clone = Object.assign({}, obj);
|
|
195
|
+
Object.keys(clone).forEach(
|
|
196
|
+
key => (clone[key] = typeof obj[key] === 'object' ? deepClone(obj[key]) : obj[key])
|
|
197
|
+
);
|
|
198
|
+
return Array.isArray(obj) && obj.length
|
|
199
|
+
? (clone.length = obj.length) && Array.from(clone)
|
|
200
|
+
: Array.isArray(obj)
|
|
201
|
+
? Array.from(obj)
|
|
202
|
+
: clone;
|
|
203
|
+
};
|
|
204
|
+
const deepFlatten = arr => [].concat(...arr.map(v => (Array.isArray(v) ? deepFlatten(v) : v)));
|
|
205
|
+
const deepFreeze = obj =>
|
|
206
|
+
Object.keys(obj).forEach(prop =>
|
|
207
|
+
!(obj[prop] instanceof Object) || Object.isFrozen(obj[prop]) ? null : deepFreeze(obj[prop])
|
|
208
|
+
) || Object.freeze(obj);
|
|
209
|
+
const deepGet = (obj, keys) => keys.reduce((xs, x) => (xs && xs[x] ? xs[x] : null), obj);
|
|
210
|
+
const deepMapKeys = (obj, f) =>
|
|
211
|
+
Array.isArray(obj)
|
|
212
|
+
? obj.map(val => deepMapKeys(val, f))
|
|
213
|
+
: typeof obj === 'object'
|
|
214
|
+
? Object.keys(obj).reduce((acc, current) => {
|
|
215
|
+
const val = obj[current];
|
|
216
|
+
acc[f(current)] =
|
|
217
|
+
val !== null && typeof val === 'object' ? deepMapKeys(val, f) : (acc[f(current)] = val);
|
|
218
|
+
return acc;
|
|
219
|
+
}, {})
|
|
220
|
+
: obj;
|
|
221
|
+
const defaults = (obj, ...defs) => Object.assign({}, obj, ...defs.reverse(), obj);
|
|
222
|
+
const defer = (fn, ...args) => setTimeout(fn, 1, ...args);
|
|
223
|
+
const degreesToRads = deg => (deg * Math.PI) / 180.0;
|
|
224
|
+
const delay = (fn, wait, ...args) => setTimeout(fn, wait, ...args);
|
|
225
|
+
const detectDeviceType = () =>
|
|
226
|
+
/Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent)
|
|
227
|
+
? 'Mobile'
|
|
228
|
+
: 'Desktop';
|
|
229
|
+
const difference = (a, b) => {
|
|
230
|
+
const s = new Set(b);
|
|
231
|
+
return a.filter(x => !s.has(x));
|
|
232
|
+
};
|
|
233
|
+
const differenceBy = (a, b, fn) => {
|
|
234
|
+
const s = new Set(b.map(fn));
|
|
235
|
+
return a.map(fn).filter(el => !s.has(el));
|
|
236
|
+
};
|
|
237
|
+
const differenceWith = (arr, val, comp) => arr.filter(a => val.findIndex(b => comp(a, b)) === -1);
|
|
238
|
+
// new add
|
|
239
|
+
// xor 返回两个集合不存在
|
|
240
|
+
const xor = (a, b) => {
|
|
241
|
+
const s = new Set(a.concat(b));
|
|
242
|
+
return a.concat(b).filter(el=>!s.has(el))
|
|
243
|
+
};
|
|
244
|
+
const xorBy = (a, b, fn) => {
|
|
245
|
+
const s = new Set(a.map(fn).concat(b.map(fn)));
|
|
246
|
+
return a.concat(b).map(fn).filter(el=>!s.has(el))
|
|
247
|
+
};
|
|
248
|
+
const xorWith = (arr, val, comp) => {
|
|
249
|
+
return arr.filter(el=>!val.some(d=>comp(el,d)))
|
|
250
|
+
}
|
|
251
|
+
const dig = (obj, target) =>
|
|
252
|
+
target in obj
|
|
253
|
+
? obj[target]
|
|
254
|
+
: Object.values(obj).reduce((acc, val) => {
|
|
255
|
+
if (acc !== undefined) return acc;
|
|
256
|
+
if (typeof val === 'object') return dig(val, target);
|
|
257
|
+
}, undefined);
|
|
258
|
+
const digitize = n => [...`${n}`].map(i => parseInt(i));
|
|
259
|
+
const distance = (x0, y0, x1, y1) => Math.hypot(x1 - x0, y1 - y0);
|
|
260
|
+
const drop = (arr, n = 1) => arr.slice(n);
|
|
261
|
+
const dropRight = (arr, n = 1) => arr.slice(0, -n);
|
|
262
|
+
const dropRightWhile = (arr, func) => {
|
|
263
|
+
let rightIndex = arr.length;
|
|
264
|
+
while (rightIndex-- && !func(arr[rightIndex]));
|
|
265
|
+
return arr.slice(0, rightIndex + 1);
|
|
266
|
+
};
|
|
267
|
+
const dropWhile = (arr, func) => {
|
|
268
|
+
while (arr.length > 0 && !func(arr[0])) arr = arr.slice(1);
|
|
269
|
+
return arr;
|
|
270
|
+
};
|
|
271
|
+
const elementContains = (parent, child) => parent !== child && parent.contains(child);
|
|
272
|
+
const elementIsVisibleInViewport = (el, partiallyVisible = false) => {
|
|
273
|
+
const { top, left, bottom, right } = el.getBoundingClientRect();
|
|
274
|
+
const { innerHeight, innerWidth } = window;
|
|
275
|
+
return partiallyVisible
|
|
276
|
+
? ((top > 0 && top < innerHeight) || (bottom > 0 && bottom < innerHeight)) &&
|
|
277
|
+
((left > 0 && left < innerWidth) || (right > 0 && right < innerWidth))
|
|
278
|
+
: top >= 0 && left >= 0 && bottom <= innerHeight && right <= innerWidth;
|
|
279
|
+
};
|
|
280
|
+
const elo = ([...ratings], kFactor = 32, selfRating) => {
|
|
281
|
+
const [a, b] = ratings;
|
|
282
|
+
const expectedScore = (self, opponent) => 1 / (1 + 10 ** ((opponent - self) / 400));
|
|
283
|
+
const newRating = (rating, i) =>
|
|
284
|
+
(selfRating || rating) + kFactor * (i - expectedScore(i ? a : b, i ? b : a));
|
|
285
|
+
if (ratings.length === 2) return [newRating(a, 1), newRating(b, 0)];
|
|
286
|
+
|
|
287
|
+
for (let i = 0, len = ratings.length; i < len; i++) {
|
|
288
|
+
let j = i;
|
|
289
|
+
while (j < len - 1) {
|
|
290
|
+
j++;
|
|
291
|
+
[ratings[i], ratings[j]] = elo([ratings[i], ratings[j]], kFactor);
|
|
292
|
+
}
|
|
293
|
+
}
|
|
294
|
+
return ratings;
|
|
295
|
+
};
|
|
296
|
+
const equals = (a, b) => {
|
|
297
|
+
if (a === b) return true;
|
|
298
|
+
if (a instanceof Date && b instanceof Date) return a.getTime() === b.getTime();
|
|
299
|
+
if (!a || !b || (typeof a !== 'object' && typeof b !== 'object')) return a === b;
|
|
300
|
+
if (a === null || a === undefined || b === null || b === undefined) return false;
|
|
301
|
+
if (a.prototype !== b.prototype) return false;
|
|
302
|
+
let keys = Object.keys(a);
|
|
303
|
+
if (keys.length !== Object.keys(b).length) return false;
|
|
304
|
+
return keys.every(k => equals(a[k], b[k]));
|
|
305
|
+
};
|
|
306
|
+
const escapeHTML = str =>
|
|
307
|
+
str.replace(
|
|
308
|
+
/[&<>'"]/g,
|
|
309
|
+
tag =>
|
|
310
|
+
({
|
|
311
|
+
'&': '&',
|
|
312
|
+
'<': '<',
|
|
313
|
+
'>': '>',
|
|
314
|
+
"'": ''',
|
|
315
|
+
'"': '"'
|
|
316
|
+
}[tag] || tag)
|
|
317
|
+
);
|
|
318
|
+
const escapeRegExp = str => str.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
|
|
319
|
+
const everyNth = (arr, nth) => arr.filter((e, i) => i % nth === nth - 1);
|
|
320
|
+
const extendHex = shortHex =>
|
|
321
|
+
'#' +
|
|
322
|
+
shortHex
|
|
323
|
+
.slice(shortHex.startsWith('#') ? 1 : 0)
|
|
324
|
+
.split('')
|
|
325
|
+
.map(x => x + x)
|
|
326
|
+
.join('');
|
|
327
|
+
const factorial = n =>
|
|
328
|
+
n < 0
|
|
329
|
+
? (() => {
|
|
330
|
+
throw new TypeError('Negative numbers are not allowed!');
|
|
331
|
+
})()
|
|
332
|
+
: n <= 1
|
|
333
|
+
? 1
|
|
334
|
+
: n * factorial(n - 1);
|
|
335
|
+
const fibonacci = n =>
|
|
336
|
+
Array.from({ length: n }).reduce(
|
|
337
|
+
(acc, val, i) => acc.concat(i > 1 ? acc[i - 1] + acc[i - 2] : i),
|
|
338
|
+
[]
|
|
339
|
+
);
|
|
340
|
+
const filterFalsy = arr => arr.filter(Boolean);
|
|
341
|
+
const filterNonUnique = arr => arr.filter(i => arr.indexOf(i) === arr.lastIndexOf(i));
|
|
342
|
+
const filterNonUniqueBy = (arr, fn) =>
|
|
343
|
+
arr.filter((v, i) => arr.every((x, j) => (i === j) === fn(v, x, i, j)));
|
|
344
|
+
const findKey = (obj, fn) => Object.keys(obj).find(key => fn(obj[key], key, obj));
|
|
345
|
+
const findLast = (arr, fn) => arr.filter(fn).pop();
|
|
346
|
+
const findLastIndex = (arr, fn) =>
|
|
347
|
+
(arr
|
|
348
|
+
.map((val, i) => [i, val])
|
|
349
|
+
.filter(([i, val]) => fn(val, i, arr))
|
|
350
|
+
.pop() || [-1])[0];
|
|
351
|
+
const findLastKey = (obj, fn) =>
|
|
352
|
+
Object.keys(obj)
|
|
353
|
+
.reverse()
|
|
354
|
+
.find(key => fn(obj[key], key, obj));
|
|
355
|
+
const flatten = (arr, depth = 1) =>
|
|
356
|
+
arr.reduce((a, v) => a.concat(depth > 1 && Array.isArray(v) ? flatten(v, depth - 1) : v), []);
|
|
357
|
+
const flattenObject = (obj, prefix = '') =>
|
|
358
|
+
Object.keys(obj).reduce((acc, k) => {
|
|
359
|
+
const pre = prefix.length ? prefix + '.' : '';
|
|
360
|
+
if (typeof obj[k] === 'object') Object.assign(acc, flattenObject(obj[k], pre + k));
|
|
361
|
+
else acc[pre + k] = obj[k];
|
|
362
|
+
return acc;
|
|
363
|
+
}, {});
|
|
364
|
+
const flip = fn => (first, ...rest) => fn(...rest, first);
|
|
365
|
+
const forEachRight = (arr, callback) =>
|
|
366
|
+
arr
|
|
367
|
+
.slice(0)
|
|
368
|
+
.reverse()
|
|
369
|
+
.forEach(callback);
|
|
370
|
+
const formatDuration = ms => {
|
|
371
|
+
if (ms < 0) ms = -ms;
|
|
372
|
+
const time = {
|
|
373
|
+
day: Math.floor(ms / 86400000),
|
|
374
|
+
hour: Math.floor(ms / 3600000) % 24,
|
|
375
|
+
minute: Math.floor(ms / 60000) % 60,
|
|
376
|
+
second: Math.floor(ms / 1000) % 60,
|
|
377
|
+
millisecond: Math.floor(ms) % 1000
|
|
378
|
+
};
|
|
379
|
+
return Object.entries(time)
|
|
380
|
+
.filter(val => val[1] !== 0)
|
|
381
|
+
.map(([key, val]) => `${val} ${key}${val !== 1 ? 's' : ''}`)
|
|
382
|
+
.join(', ');
|
|
383
|
+
};
|
|
384
|
+
const formToObject = form =>
|
|
385
|
+
Array.from(new FormData(form)).reduce(
|
|
386
|
+
(acc, [key, value]) => ({
|
|
387
|
+
...acc,
|
|
388
|
+
[key]: value
|
|
389
|
+
}),
|
|
390
|
+
{}
|
|
391
|
+
);
|
|
392
|
+
const forOwn = (obj, fn) => Object.keys(obj).forEach(key => fn(obj[key], key, obj));
|
|
393
|
+
const forOwnRight = (obj, fn) =>
|
|
394
|
+
Object.keys(obj)
|
|
395
|
+
.reverse()
|
|
396
|
+
.forEach(key => fn(obj[key], key, obj));
|
|
397
|
+
const fromCamelCase = (str, separator = '_') =>
|
|
398
|
+
str
|
|
399
|
+
.replace(/([a-z\d])([A-Z])/g, '$1' + separator + '$2')
|
|
400
|
+
.replace(/([A-Z]+)([A-Z][a-z\d]+)/g, '$1' + separator + '$2')
|
|
401
|
+
.toLowerCase();
|
|
402
|
+
const functionName = fn => (console.debug(fn.name), fn);
|
|
403
|
+
const functions = (obj, inherited = false) =>
|
|
404
|
+
(inherited
|
|
405
|
+
? [...Object.keys(obj), ...Object.keys(Object.getPrototypeOf(obj))]
|
|
406
|
+
: Object.keys(obj)
|
|
407
|
+
).filter(key => typeof obj[key] === 'function');
|
|
408
|
+
const gcd = (...arr) => {
|
|
409
|
+
const _gcd = (x, y) => (!y ? x : gcd(y, x % y));
|
|
410
|
+
return [...arr].reduce((a, b) => _gcd(a, b));
|
|
411
|
+
};
|
|
412
|
+
const geometricProgression = (end, start = 1, step = 2) =>
|
|
413
|
+
Array.from({ length: Math.floor(Math.log(end / start) / Math.log(step)) + 1 }).map(
|
|
414
|
+
(v, i) => start * step ** i
|
|
415
|
+
);
|
|
416
|
+
const get = (from, ...selectors) =>
|
|
417
|
+
[...selectors].map(s =>
|
|
418
|
+
s
|
|
419
|
+
.replace(/\[([^\[\]]*)\]/g, '.$1.')
|
|
420
|
+
.split('.')
|
|
421
|
+
.filter(t => t !== '')
|
|
422
|
+
.reduce((prev, cur) => prev && prev[cur], from)
|
|
423
|
+
);
|
|
424
|
+
const getColonTimeFromDate = date => date.toTimeString().slice(0, 8);
|
|
425
|
+
const getDaysDiffBetweenDates = (dateInitial, dateFinal) =>
|
|
426
|
+
(dateFinal - dateInitial) / (1000 * 3600 * 24);
|
|
427
|
+
const getImages = (el, includeDuplicates = false) => {
|
|
428
|
+
const images = [...el.getElementsByTagName('img')].map(img => img.getAttribute('src'));
|
|
429
|
+
return includeDuplicates ? images : [...new Set(images)];
|
|
430
|
+
};
|
|
431
|
+
const getMeridiemSuffixOfInteger = num =>
|
|
432
|
+
num === 0 || num === 24
|
|
433
|
+
? 12 + 'am'
|
|
434
|
+
: num === 12
|
|
435
|
+
? 12 + 'pm'
|
|
436
|
+
: num < 12
|
|
437
|
+
? (num % 12) + 'am'
|
|
438
|
+
: (num % 12) + 'pm';
|
|
439
|
+
const getScrollPosition = (el = window) => ({
|
|
440
|
+
x: el.pageXOffset !== undefined ? el.pageXOffset : el.scrollLeft,
|
|
441
|
+
y: el.pageYOffset !== undefined ? el.pageYOffset : el.scrollTop
|
|
442
|
+
});
|
|
443
|
+
const getStyle = (el, ruleName) => getComputedStyle(el)[ruleName];
|
|
444
|
+
const getType = v =>
|
|
445
|
+
v === undefined ? 'undefined' : v === null ? 'null' : v.constructor.name.toLowerCase();
|
|
446
|
+
const getURLParameters = url =>
|
|
447
|
+
(url.match(/([^?=&]+)(=([^&]*))/g) || []).reduce(
|
|
448
|
+
(a, v) => ((a[v.slice(0, v.indexOf('='))] = v.slice(v.indexOf('=') + 1)), a),
|
|
449
|
+
{}
|
|
450
|
+
);
|
|
451
|
+
const groupBy = (arr, fn) =>
|
|
452
|
+
arr.map(typeof fn === 'function' ? fn : val => val[fn]).reduce((acc, val, i) => {
|
|
453
|
+
acc[val] = (acc[val] || []).concat(arr[i]);
|
|
454
|
+
return acc;
|
|
455
|
+
}, {});
|
|
456
|
+
const hammingDistance = (num1, num2) => ((num1 ^ num2).toString(2).match(/1/g) || '').length;
|
|
457
|
+
const hasClass = (el, className) => el.classList.contains(className);
|
|
458
|
+
const hasFlags = (...flags) =>
|
|
459
|
+
flags.every(flag => process.argv.includes(/^-{1,2}/.test(flag) ? flag : '--' + flag));
|
|
460
|
+
const hashBrowser = val =>
|
|
461
|
+
crypto.subtle.digest('SHA-256', new TextEncoder('utf-8').encode(val)).then(h => {
|
|
462
|
+
let hexes = [],
|
|
463
|
+
view = new DataView(h);
|
|
464
|
+
for (let i = 0; i < view.byteLength; i += 4)
|
|
465
|
+
hexes.push(('00000000' + view.getUint32(i).toString(16)).slice(-8));
|
|
466
|
+
return hexes.join('');
|
|
467
|
+
});
|
|
468
|
+
const hashNode = val =>
|
|
469
|
+
new Promise(resolve =>
|
|
470
|
+
setTimeout(
|
|
471
|
+
() =>
|
|
472
|
+
resolve(
|
|
473
|
+
crypto
|
|
474
|
+
.createHash('sha256')
|
|
475
|
+
.update(val)
|
|
476
|
+
.digest('hex')
|
|
477
|
+
),
|
|
478
|
+
0
|
|
479
|
+
)
|
|
480
|
+
);
|
|
481
|
+
const head = arr => arr[0];
|
|
482
|
+
const hexToRGB = hex => {
|
|
483
|
+
let alpha = false,
|
|
484
|
+
h = hex.slice(hex.startsWith('#') ? 1 : 0);
|
|
485
|
+
if (h.length === 3) h = [...h].map(x => x + x).join('');
|
|
486
|
+
else if (h.length === 8) alpha = true;
|
|
487
|
+
h = parseInt(h, 16);
|
|
488
|
+
return (
|
|
489
|
+
'rgb' +
|
|
490
|
+
(alpha ? 'a' : '') +
|
|
491
|
+
'(' +
|
|
492
|
+
(h >>> (alpha ? 24 : 16)) +
|
|
493
|
+
', ' +
|
|
494
|
+
((h & (alpha ? 0x00ff0000 : 0x00ff00)) >>> (alpha ? 16 : 8)) +
|
|
495
|
+
', ' +
|
|
496
|
+
((h & (alpha ? 0x0000ff00 : 0x0000ff)) >>> (alpha ? 8 : 0)) +
|
|
497
|
+
(alpha ? `, ${h & 0x000000ff}` : '') +
|
|
498
|
+
')'
|
|
499
|
+
);
|
|
500
|
+
};
|
|
501
|
+
const hide = (...el) => [...el].forEach(e => (e.style.display = 'none'));
|
|
502
|
+
const httpGet = (url, callback, err = console.error) => {
|
|
503
|
+
const request = new XMLHttpRequest();
|
|
504
|
+
request.open('GET', url, true);
|
|
505
|
+
request.onload = () => callback(request.responseText);
|
|
506
|
+
request.onerror = () => err(request);
|
|
507
|
+
request.send();
|
|
508
|
+
};
|
|
509
|
+
const httpPost = (url, data, callback, err = console.error) => {
|
|
510
|
+
const request = new XMLHttpRequest();
|
|
511
|
+
request.open('POST', url, true);
|
|
512
|
+
request.setRequestHeader('Content-type', 'application/json; charset=utf-8');
|
|
513
|
+
request.onload = () => callback(request.responseText);
|
|
514
|
+
request.onerror = () => err(request);
|
|
515
|
+
request.send(data);
|
|
516
|
+
};
|
|
517
|
+
const httpsRedirect = () => {
|
|
518
|
+
if (location.protocol !== 'https:') location.replace('https://' + location.href.split('//')[1]);
|
|
519
|
+
};
|
|
520
|
+
const hz = (fn, iterations = 100) => {
|
|
521
|
+
const before = performance.now();
|
|
522
|
+
for (let i = 0; i < iterations; i++) fn();
|
|
523
|
+
return (1000 * iterations) / (performance.now() - before);
|
|
524
|
+
};
|
|
525
|
+
const indentString = (str, count, indent = ' ') => str.replace(/^/gm, indent.repeat(count));
|
|
526
|
+
const indexOfAll = (arr, val) => arr.reduce((acc, el, i) => (el === val ? [...acc, i] : acc), []);
|
|
527
|
+
const initial = arr => arr.slice(0, -1);
|
|
528
|
+
const initialize2DArray = (w, h, val = null) =>
|
|
529
|
+
Array.from({ length: h }).map(() => Array.from({ length: w }).fill(val));
|
|
530
|
+
const initializeArrayWithRange = (end, start = 0, step = 1) =>
|
|
531
|
+
Array.from({ length: Math.ceil((end - start + 1) / step) }, (v, i) => i * step + start);
|
|
532
|
+
const initializeArrayWithRangeRight = (end, start = 0, step = 1) =>
|
|
533
|
+
Array.from({ length: Math.ceil((end + 1 - start) / step) }).map(
|
|
534
|
+
(v, i, arr) => (arr.length - i - 1) * step + start
|
|
535
|
+
);
|
|
536
|
+
const initializeArrayWithValues = (n, val = 0) => Array(n).fill(val);
|
|
537
|
+
const initializeNDArray = (val, ...args) =>
|
|
538
|
+
args.length === 0
|
|
539
|
+
? val
|
|
540
|
+
: Array.from({ length: args[0] }).map(() => initializeNDArray(val, ...args.slice(1)));
|
|
541
|
+
const inRange = (n, start, end = null) => {
|
|
542
|
+
if (end && start > end) [end, start] = [start, end];
|
|
543
|
+
return end == null ? n >= 0 && n < start : n >= start && n < end;
|
|
544
|
+
};
|
|
545
|
+
const insertAfter = (el, htmlString) => el.insertAdjacentHTML('afterend', htmlString);
|
|
546
|
+
const insertBefore = (el, htmlString) => el.insertAdjacentHTML('beforebegin', htmlString);
|
|
547
|
+
const intersection = (a, b) => {
|
|
548
|
+
const s = new Set(b);
|
|
549
|
+
return a.filter(x => s.has(x));
|
|
550
|
+
};
|
|
551
|
+
const intersectionBy = (a, b, fn) => {
|
|
552
|
+
const s = new Set(b.map(fn));
|
|
553
|
+
return a.filter(x => s.has(fn(x)));
|
|
554
|
+
};
|
|
555
|
+
const intersectionWith = (a, b, comp) => a.filter(x => b.findIndex(y => comp(x, y)) !== -1);
|
|
556
|
+
const invertKeyValues = (obj, fn) =>
|
|
557
|
+
Object.keys(obj).reduce((acc, key) => {
|
|
558
|
+
const val = fn ? fn(obj[key]) : obj[key];
|
|
559
|
+
acc[val] = acc[val] || [];
|
|
560
|
+
acc[val].push(key);
|
|
561
|
+
return acc;
|
|
562
|
+
}, {});
|
|
563
|
+
const is = (type, val) => ![, null].includes(val) && val.constructor === type;
|
|
564
|
+
const isAbsoluteURL = str => /^[a-z][a-z0-9+.-]*:/.test(str);
|
|
565
|
+
const isAfterDate = (dateA, dateB) => dateA > dateB;
|
|
566
|
+
const isAnagram = (str1, str2) => {
|
|
567
|
+
const normalize = str =>
|
|
568
|
+
str
|
|
569
|
+
.toLowerCase()
|
|
570
|
+
.replace(/[^a-z0-9]/gi, '')
|
|
571
|
+
.split('')
|
|
572
|
+
.sort()
|
|
573
|
+
.join('');
|
|
574
|
+
return normalize(str1) === normalize(str2);
|
|
575
|
+
};
|
|
576
|
+
const isArrayLike = obj => obj != null && typeof obj[Symbol.iterator] === 'function';
|
|
577
|
+
const isBeforeDate = (dateA, dateB) => dateA < dateB;
|
|
578
|
+
const isBoolean = val => typeof val === 'boolean';
|
|
579
|
+
const isBrowser = () => ![typeof window, typeof document].includes('undefined');
|
|
580
|
+
const isBrowserTabFocused = () => !document.hidden;
|
|
581
|
+
const isDivisible = (dividend, divisor) => dividend % divisor === 0;
|
|
582
|
+
const isDuplexStream = val =>
|
|
583
|
+
val !== null &&
|
|
584
|
+
typeof val === 'object' &&
|
|
585
|
+
typeof val.pipe === 'function' &&
|
|
586
|
+
typeof val._read === 'function' &&
|
|
587
|
+
typeof val._readableState === 'object' &&
|
|
588
|
+
typeof val._write === 'function' &&
|
|
589
|
+
typeof val._writableState === 'object';
|
|
590
|
+
const isEmpty = val => val == null || !(Object.keys(val) || val).length;
|
|
591
|
+
const isEven = num => num % 2 === 0;
|
|
592
|
+
const isFunction = val => typeof val === 'function';
|
|
593
|
+
const isLowerCase = str => str === str.toLowerCase();
|
|
594
|
+
const isNegativeZero = val => val === 0 && 1 / val === -Infinity;
|
|
595
|
+
const isNil = val => val === undefined || val === null;
|
|
596
|
+
const isNull = val => val === null;
|
|
597
|
+
const isNumber = val => typeof val === 'number' && val === val;
|
|
598
|
+
const isObject = obj => obj === Object(obj);
|
|
599
|
+
const isObjectLike = val => val !== null && typeof val === 'object';
|
|
600
|
+
const isPlainObject = val => !!val && typeof val === 'object' && val.constructor === Object;
|
|
601
|
+
const isPrime = num => {
|
|
602
|
+
const boundary = Math.floor(Math.sqrt(num));
|
|
603
|
+
for (var i = 2; i <= boundary; i++) if (num % i === 0) return false;
|
|
604
|
+
return num >= 2;
|
|
605
|
+
};
|
|
606
|
+
const isPrimitive = val => Object(val) !== val;
|
|
607
|
+
const isPromiseLike = obj =>
|
|
608
|
+
obj !== null &&
|
|
609
|
+
(typeof obj === 'object' || typeof obj === 'function') &&
|
|
610
|
+
typeof obj.then === 'function';
|
|
611
|
+
const isReadableStream = val =>
|
|
612
|
+
val !== null &&
|
|
613
|
+
typeof val === 'object' &&
|
|
614
|
+
typeof val.pipe === 'function' &&
|
|
615
|
+
typeof val._read === 'function' &&
|
|
616
|
+
typeof val._readableState === 'object';
|
|
617
|
+
const isSameDate = (dateA, dateB) => dateA.toISOString() === dateB.toISOString();
|
|
618
|
+
const isSorted = arr => {
|
|
619
|
+
let direction = -(arr[0] - arr[1]);
|
|
620
|
+
for (let [i, val] of arr.entries()) {
|
|
621
|
+
direction = !direction ? -(arr[i - 1] - arr[i]) : direction;
|
|
622
|
+
if (i === arr.length - 1) return !direction ? 0 : direction;
|
|
623
|
+
else if ((val - arr[i + 1]) * direction > 0) return 0;
|
|
624
|
+
}
|
|
625
|
+
};
|
|
626
|
+
const isStream = val => val !== null && typeof val === 'object' && typeof val.pipe === 'function';
|
|
627
|
+
const isString = val => typeof val === 'string';
|
|
628
|
+
const isSymbol = val => typeof val === 'symbol';
|
|
629
|
+
const isTravisCI = () => 'TRAVIS' in process.env && 'CI' in process.env;
|
|
630
|
+
const isUndefined = val => val === undefined;
|
|
631
|
+
const isUpperCase = str => str === str.toUpperCase();
|
|
632
|
+
const isValidJSON = str => {
|
|
633
|
+
try {
|
|
634
|
+
JSON.parse(str);
|
|
635
|
+
return true;
|
|
636
|
+
} catch (e) {
|
|
637
|
+
return false;
|
|
638
|
+
}
|
|
639
|
+
};
|
|
640
|
+
const isWeekday = (t = new Date()) => {
|
|
641
|
+
return t.getDay() % 6 !== 0;
|
|
642
|
+
};
|
|
643
|
+
const isWeekend = (t = new Date()) => {
|
|
644
|
+
return t.getDay() % 6 === 0;
|
|
645
|
+
};
|
|
646
|
+
const isWritableStream = val =>
|
|
647
|
+
val !== null &&
|
|
648
|
+
typeof val === 'object' &&
|
|
649
|
+
typeof val.pipe === 'function' &&
|
|
650
|
+
typeof val._write === 'function' &&
|
|
651
|
+
typeof val._writableState === 'object';
|
|
652
|
+
const join = (arr, separator = ',', end = separator) =>
|
|
653
|
+
arr.reduce(
|
|
654
|
+
(acc, val, i) =>
|
|
655
|
+
i === arr.length - 2
|
|
656
|
+
? acc + val + end
|
|
657
|
+
: i === arr.length - 1
|
|
658
|
+
? acc + val
|
|
659
|
+
: acc + val + separator,
|
|
660
|
+
''
|
|
661
|
+
);
|
|
662
|
+
const JSONtoCSV = (arr, columns, delimiter = ',') =>
|
|
663
|
+
[
|
|
664
|
+
columns.join(delimiter),
|
|
665
|
+
...arr.map(obj =>
|
|
666
|
+
columns.reduce(
|
|
667
|
+
(acc, key) => `${acc}${!acc.length ? '' : delimiter}"${!obj[key] ? '' : obj[key]}"`,
|
|
668
|
+
''
|
|
669
|
+
)
|
|
670
|
+
)
|
|
671
|
+
].join('\n');
|
|
672
|
+
const JSONToFile = (obj, filename) =>
|
|
673
|
+
fs.writeFile(`${filename}.json`, JSON.stringify(obj, null, 2));
|
|
674
|
+
const last = arr => arr[arr.length - 1];
|
|
675
|
+
const lcm = (...arr) => {
|
|
676
|
+
const gcd = (x, y) => (!y ? x : gcd(y, x % y));
|
|
677
|
+
const _lcm = (x, y) => (x * y) / gcd(x, y);
|
|
678
|
+
return [...arr].reduce((a, b) => _lcm(a, b));
|
|
679
|
+
};
|
|
680
|
+
const longestItem = (...vals) => vals.reduce((a, x) => (x.length > a.length ? x : a));
|
|
681
|
+
const lowercaseKeys = obj =>
|
|
682
|
+
Object.keys(obj).reduce((acc, key) => {
|
|
683
|
+
acc[key.toLowerCase()] = obj[key];
|
|
684
|
+
return acc;
|
|
685
|
+
}, {});
|
|
686
|
+
const luhnCheck = num => {
|
|
687
|
+
let arr = (num + '')
|
|
688
|
+
.split('')
|
|
689
|
+
.reverse()
|
|
690
|
+
.map(x => parseInt(x));
|
|
691
|
+
let lastDigit = arr.splice(0, 1)[0];
|
|
692
|
+
let sum = arr.reduce((acc, val, i) => (i % 2 !== 0 ? acc + val : acc + ((val * 2) % 9) || 9), 0);
|
|
693
|
+
sum += lastDigit;
|
|
694
|
+
return sum % 10 === 0;
|
|
695
|
+
};
|
|
696
|
+
const mapKeys = (obj, fn) =>
|
|
697
|
+
Object.keys(obj).reduce((acc, k) => {
|
|
698
|
+
acc[fn(obj[k], k, obj)] = obj[k];
|
|
699
|
+
return acc;
|
|
700
|
+
}, {});
|
|
701
|
+
const mapNumRange = (num, inMin, inMax, outMin, outMax) =>
|
|
702
|
+
((num - inMin) * (outMax - outMin)) / (inMax - inMin) + outMin;
|
|
703
|
+
const mapObject = (arr, fn) =>
|
|
704
|
+
(a => (
|
|
705
|
+
(a = [arr, arr.map(fn)]), a[0].reduce((acc, val, ind) => ((acc[val] = a[1][ind]), acc), {})
|
|
706
|
+
))();
|
|
707
|
+
const mapString = (str, fn) =>
|
|
708
|
+
str
|
|
709
|
+
.split('')
|
|
710
|
+
.map((c, i) => fn(c, i, str))
|
|
711
|
+
.join('');
|
|
712
|
+
const mapValues = (obj, fn) =>
|
|
713
|
+
Object.keys(obj).reduce((acc, k) => {
|
|
714
|
+
acc[k] = fn(obj[k], k, obj);
|
|
715
|
+
return acc;
|
|
716
|
+
}, {});
|
|
717
|
+
const mask = (cc, num = 4, mask = '*') => `${cc}`.slice(-num).padStart(`${cc}`.length, mask);
|
|
718
|
+
const matches = (obj, source) =>
|
|
719
|
+
Object.keys(source).every(key => obj.hasOwnProperty(key) && obj[key] === source[key]);
|
|
720
|
+
const matchesWith = (obj, source, fn) =>
|
|
721
|
+
Object.keys(source).every(key =>
|
|
722
|
+
obj.hasOwnProperty(key) && fn
|
|
723
|
+
? fn(obj[key], source[key], key, obj, source)
|
|
724
|
+
: obj[key] == source[key]
|
|
725
|
+
);
|
|
726
|
+
const maxBy = (arr, fn) => Math.max(...arr.map(typeof fn === 'function' ? fn : val => val[fn]));
|
|
727
|
+
const maxDate = dates => new Date(Math.max(...dates));
|
|
728
|
+
const maxN = (arr, n = 1) => [...arr].sort((a, b) => b - a).slice(0, n);
|
|
729
|
+
const median = arr => {
|
|
730
|
+
const mid = Math.floor(arr.length / 2),
|
|
731
|
+
nums = [...arr].sort((a, b) => a - b);
|
|
732
|
+
return arr.length % 2 !== 0 ? nums[mid] : (nums[mid - 1] + nums[mid]) / 2;
|
|
733
|
+
};
|
|
734
|
+
const memoize = fn => {
|
|
735
|
+
const cache = new Map();
|
|
736
|
+
const cached = function(val) {
|
|
737
|
+
return cache.has(val) ? cache.get(val) : cache.set(val, fn.call(this, val)) && cache.get(val);
|
|
738
|
+
};
|
|
739
|
+
cached.cache = cache;
|
|
740
|
+
return cached;
|
|
741
|
+
};
|
|
742
|
+
const merge = (...objs) =>
|
|
743
|
+
[...objs].reduce(
|
|
744
|
+
(acc, obj) =>
|
|
745
|
+
Object.keys(obj).reduce((a, k) => {
|
|
746
|
+
acc[k] = acc.hasOwnProperty(k) ? [].concat(acc[k]).concat(obj[k]) : obj[k];
|
|
747
|
+
return acc;
|
|
748
|
+
}, {}),
|
|
749
|
+
{}
|
|
750
|
+
);
|
|
751
|
+
const midpoint = ([x1, y1], [x2, y2]) => [(x1 + x2) / 2, (y1 + y2) / 2];
|
|
752
|
+
const minBy = (arr, fn) => Math.min(...arr.map(typeof fn === 'function' ? fn : val => val[fn]));
|
|
753
|
+
const minDate = dates => new Date(Math.min(...dates));
|
|
754
|
+
const minN = (arr, n = 1) => [...arr].sort((a, b) => a - b).slice(0, n);
|
|
755
|
+
const mostPerformant = (fns, iterations = 10000) => {
|
|
756
|
+
const times = fns.map(fn => {
|
|
757
|
+
const before = performance.now();
|
|
758
|
+
for (let i = 0; i < iterations; i++) fn();
|
|
759
|
+
return performance.now() - before;
|
|
760
|
+
});
|
|
761
|
+
return times.indexOf(Math.min(...times));
|
|
762
|
+
};
|
|
763
|
+
const negate = func => (...args) => !func(...args);
|
|
764
|
+
const nest = (items, id = null, link = 'parent_id') =>
|
|
765
|
+
items
|
|
766
|
+
.filter(item => item[link] === id)
|
|
767
|
+
.map(item => ({ ...item, children: nest(items, item.id) }));
|
|
768
|
+
const nodeListToArray = nodeList => [...nodeList];
|
|
769
|
+
const none = (arr, fn = Boolean) => !arr.some(fn);
|
|
770
|
+
const nthArg = n => (...args) => args.slice(n)[0];
|
|
771
|
+
const nthElement = (arr, n = 0) => (n === -1 ? arr.slice(n) : arr.slice(n, n + 1))[0];
|
|
772
|
+
const objectFromPairs = arr => arr.reduce((a, [key, val]) => ((a[key] = val), a), {});
|
|
773
|
+
const objectToPairs = obj => Object.keys(obj).map(k => [k, obj[k]]);
|
|
774
|
+
const observeMutations = (element, callback, options) => {
|
|
775
|
+
const observer = new MutationObserver(mutations => mutations.forEach(m => callback(m)));
|
|
776
|
+
observer.observe(
|
|
777
|
+
element,
|
|
778
|
+
Object.assign(
|
|
779
|
+
{
|
|
780
|
+
childList: true,
|
|
781
|
+
attributes: true,
|
|
782
|
+
attributeOldValue: true,
|
|
783
|
+
characterData: true,
|
|
784
|
+
characterDataOldValue: true,
|
|
785
|
+
subtree: true
|
|
786
|
+
},
|
|
787
|
+
options
|
|
788
|
+
)
|
|
789
|
+
);
|
|
790
|
+
return observer;
|
|
791
|
+
};
|
|
792
|
+
const off = (el, evt, fn, opts = false) => el.removeEventListener(evt, fn, opts);
|
|
793
|
+
const offset = (arr, offset) => [...arr.slice(offset), ...arr.slice(0, offset)];
|
|
794
|
+
const omit = (obj, arr) =>
|
|
795
|
+
Object.keys(obj)
|
|
796
|
+
.filter(k => !arr.includes(k))
|
|
797
|
+
.reduce((acc, key) => ((acc[key] = obj[key]), acc), {});
|
|
798
|
+
const omitBy = (obj, fn) =>
|
|
799
|
+
Object.keys(obj)
|
|
800
|
+
.filter(k => !fn(obj[k], k))
|
|
801
|
+
.reduce((acc, key) => ((acc[key] = obj[key]), acc), {});
|
|
802
|
+
const on = (el, evt, fn, opts = {}) => {
|
|
803
|
+
const delegatorFn = e => e.target.matches(opts.target) && fn.call(e.target, e);
|
|
804
|
+
el.addEventListener(evt, opts.target ? delegatorFn : fn, opts.options || false);
|
|
805
|
+
if (opts.target) return delegatorFn;
|
|
806
|
+
};
|
|
807
|
+
const once = fn => {
|
|
808
|
+
let called = false;
|
|
809
|
+
return function(...args) {
|
|
810
|
+
if (called) return;
|
|
811
|
+
called = true;
|
|
812
|
+
return fn.apply(this, args);
|
|
813
|
+
};
|
|
814
|
+
};
|
|
815
|
+
const onUserInputChange = callback => {
|
|
816
|
+
let type = 'mouse',
|
|
817
|
+
lastTime = 0;
|
|
818
|
+
const mousemoveHandler = () => {
|
|
819
|
+
const now = performance.now();
|
|
820
|
+
if (now - lastTime < 20)
|
|
821
|
+
(type = 'mouse'), callback(type), document.removeEventListener('mousemove', mousemoveHandler);
|
|
822
|
+
lastTime = now;
|
|
823
|
+
};
|
|
824
|
+
document.addEventListener('touchstart', () => {
|
|
825
|
+
if (type === 'touch') return;
|
|
826
|
+
(type = 'touch'), callback(type), document.addEventListener('mousemove', mousemoveHandler);
|
|
827
|
+
});
|
|
828
|
+
};
|
|
829
|
+
const orderBy = (arr, props, orders) =>
|
|
830
|
+
[...arr].sort((a, b) =>
|
|
831
|
+
props.reduce((acc, prop, i) => {
|
|
832
|
+
if (acc === 0) {
|
|
833
|
+
const [p1, p2] = orders && orders[i] === 'desc' ? [b[prop], a[prop]] : [a[prop], b[prop]];
|
|
834
|
+
acc = p1 > p2 ? 1 : p1 < p2 ? -1 : 0;
|
|
835
|
+
}
|
|
836
|
+
return acc;
|
|
837
|
+
}, 0)
|
|
838
|
+
);
|
|
839
|
+
const over = (...fns) => (...args) => fns.map(fn => fn.apply(null, args));
|
|
840
|
+
const overArgs = (fn, transforms) => (...args) => fn(...args.map((val, i) => transforms[i](val)));
|
|
841
|
+
const pad = (str, length, char = ' ') =>
|
|
842
|
+
str.padStart((str.length + length) / 2, char).padEnd(length, char);
|
|
843
|
+
const palindrome = str => {
|
|
844
|
+
const s = str.toLowerCase().replace(/[\W_]/g, '');
|
|
845
|
+
return s === [...s].reverse().join('');
|
|
846
|
+
};
|
|
847
|
+
const parseCookie = str =>
|
|
848
|
+
str
|
|
849
|
+
.split(';')
|
|
850
|
+
.map(v => v.split('='))
|
|
851
|
+
.reduce((acc, v) => {
|
|
852
|
+
acc[decodeURIComponent(v[0].trim())] = decodeURIComponent(v[1].trim());
|
|
853
|
+
return acc;
|
|
854
|
+
}, {});
|
|
855
|
+
const partial = (fn, ...partials) => (...args) => fn(...partials, ...args);
|
|
856
|
+
const partialRight = (fn, ...partials) => (...args) => fn(...args, ...partials);
|
|
857
|
+
const partition = (arr, fn) =>
|
|
858
|
+
arr.reduce(
|
|
859
|
+
(acc, val, i, arr) => {
|
|
860
|
+
acc[fn(val, i, arr) ? 0 : 1].push(val);
|
|
861
|
+
return acc;
|
|
862
|
+
},
|
|
863
|
+
[[], []]
|
|
864
|
+
);
|
|
865
|
+
const percentile = (arr, val) =>
|
|
866
|
+
(100 * arr.reduce((acc, v) => acc + (v < val ? 1 : 0) + (v === val ? 0.5 : 0), 0)) / arr.length;
|
|
867
|
+
const permutations = arr => {
|
|
868
|
+
if (arr.length <= 2) return arr.length === 2 ? [arr, [arr[1], arr[0]]] : arr;
|
|
869
|
+
return arr.reduce(
|
|
870
|
+
(acc, item, i) =>
|
|
871
|
+
acc.concat(
|
|
872
|
+
permutations([...arr.slice(0, i), ...arr.slice(i + 1)]).map(val => [item, ...val])
|
|
873
|
+
),
|
|
874
|
+
[]
|
|
875
|
+
);
|
|
876
|
+
};
|
|
877
|
+
const pick = (obj, arr) =>
|
|
878
|
+
arr.reduce((acc, curr) => (curr in obj && (acc[curr] = obj[curr]), acc), {});
|
|
879
|
+
const pickBy = (obj, fn) =>
|
|
880
|
+
Object.keys(obj)
|
|
881
|
+
.filter(k => fn(obj[k], k))
|
|
882
|
+
.reduce((acc, key) => ((acc[key] = obj[key]), acc), {});
|
|
883
|
+
const pipeAsyncFunctions = (...fns) => arg => fns.reduce((p, f) => p.then(f), Promise.resolve(arg));
|
|
884
|
+
const pipeFunctions = (...fns) => fns.reduce((f, g) => (...args) => g(f(...args)));
|
|
885
|
+
const pluralize = (val, word, plural = word + 's') => {
|
|
886
|
+
const _pluralize = (num, word, plural = word + 's') =>
|
|
887
|
+
[1, -1].includes(Number(num)) ? word : plural;
|
|
888
|
+
if (typeof val === 'object') return (num, word) => _pluralize(num, word, val[word]);
|
|
889
|
+
return _pluralize(val, word, plural);
|
|
890
|
+
};
|
|
891
|
+
const powerset = arr => arr.reduce((a, v) => a.concat(a.map(r => [v].concat(r))), [[]]);
|
|
892
|
+
const prefix = prop => {
|
|
893
|
+
const capitalizedProp = prop.charAt(0).toUpperCase() + prop.slice(1);
|
|
894
|
+
const prefixes = ['', 'webkit', 'moz', 'ms', 'o'];
|
|
895
|
+
const i = prefixes.findIndex(
|
|
896
|
+
prefix => typeof document.body.style[prefix ? prefix + capitalizedProp : prop] !== 'undefined'
|
|
897
|
+
);
|
|
898
|
+
return i !== -1 ? (i === 0 ? prop : prefixes[i] + capitalizedProp) : null;
|
|
899
|
+
};
|
|
900
|
+
const prettyBytes = (num, precision = 3, addSpace = true) => {
|
|
901
|
+
const UNITS = ['B', 'KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB'];
|
|
902
|
+
if (Math.abs(num) < 1) return num + (addSpace ? ' ' : '') + UNITS[0];
|
|
903
|
+
const exponent = Math.min(Math.floor(Math.log10(num < 0 ? -num : num) / 3), UNITS.length - 1);
|
|
904
|
+
const n = Number(((num < 0 ? -num : num) / 1000 ** exponent).toPrecision(precision));
|
|
905
|
+
return (num < 0 ? '-' : '') + n + (addSpace ? ' ' : '') + UNITS[exponent];
|
|
906
|
+
};
|
|
907
|
+
const primes = num => {
|
|
908
|
+
let arr = Array.from({ length: num - 1 }).map((x, i) => i + 2),
|
|
909
|
+
sqroot = Math.floor(Math.sqrt(num)),
|
|
910
|
+
numsTillSqroot = Array.from({ length: sqroot - 1 }).map((x, i) => i + 2);
|
|
911
|
+
numsTillSqroot.forEach(x => (arr = arr.filter(y => y % x !== 0 || y === x)));
|
|
912
|
+
return arr;
|
|
913
|
+
};
|
|
914
|
+
const promisify = func => (...args) =>
|
|
915
|
+
new Promise((resolve, reject) =>
|
|
916
|
+
func(...args, (err, result) => (err ? reject(err) : resolve(result)))
|
|
917
|
+
);
|
|
918
|
+
const pull = (arr, ...args) => {
|
|
919
|
+
let argState = Array.isArray(args[0]) ? args[0] : args;
|
|
920
|
+
let pulled = arr.filter((v, i) => !argState.includes(v));
|
|
921
|
+
arr.length = 0;
|
|
922
|
+
pulled.forEach(v => arr.push(v));
|
|
923
|
+
};
|
|
924
|
+
const pullAtIndex = (arr, pullArr) => {
|
|
925
|
+
let removed = [];
|
|
926
|
+
let pulled = arr
|
|
927
|
+
.map((v, i) => (pullArr.includes(i) ? removed.push(v) : v))
|
|
928
|
+
.filter((v, i) => !pullArr.includes(i));
|
|
929
|
+
arr.length = 0;
|
|
930
|
+
pulled.forEach(v => arr.push(v));
|
|
931
|
+
return removed;
|
|
932
|
+
};
|
|
933
|
+
const pullAtValue = (arr, pullArr) => {
|
|
934
|
+
let removed = [],
|
|
935
|
+
pushToRemove = arr.forEach((v, i) => (pullArr.includes(v) ? removed.push(v) : v)),
|
|
936
|
+
mutateTo = arr.filter((v, i) => !pullArr.includes(v));
|
|
937
|
+
arr.length = 0;
|
|
938
|
+
mutateTo.forEach(v => arr.push(v));
|
|
939
|
+
return removed;
|
|
940
|
+
};
|
|
941
|
+
const pullBy = (arr, ...args) => {
|
|
942
|
+
const length = args.length;
|
|
943
|
+
let fn = length > 1 ? args[length - 1] : undefined;
|
|
944
|
+
fn = typeof fn == 'function' ? (args.pop(), fn) : undefined;
|
|
945
|
+
let argState = (Array.isArray(args[0]) ? args[0] : args).map(val => fn(val));
|
|
946
|
+
let pulled = arr.filter((v, i) => !argState.includes(fn(v)));
|
|
947
|
+
arr.length = 0;
|
|
948
|
+
pulled.forEach(v => arr.push(v));
|
|
949
|
+
};
|
|
950
|
+
const radsToDegrees = rad => (rad * 180.0) / Math.PI;
|
|
951
|
+
const randomHexColorCode = () => {
|
|
952
|
+
let n = (Math.random() * 0xfffff * 1000000).toString(16);
|
|
953
|
+
return '#' + n.slice(0, 6);
|
|
954
|
+
};
|
|
955
|
+
const randomIntArrayInRange = (min, max, n = 1) =>
|
|
956
|
+
Array.from({ length: n }, () => Math.floor(Math.random() * (max - min + 1)) + min);
|
|
957
|
+
const randomIntegerInRange = (min, max) => Math.floor(Math.random() * (max - min + 1)) + min;
|
|
958
|
+
const randomNumberInRange = (min, max) => Math.random() * (max - min) + min;
|
|
959
|
+
const readFileLines = filename =>
|
|
960
|
+
fs
|
|
961
|
+
.readFileSync(filename)
|
|
962
|
+
.toString('UTF8')
|
|
963
|
+
.split('\n');
|
|
964
|
+
const rearg = (fn, indexes) => (...args) => fn(...indexes.map(i => args[i]));
|
|
965
|
+
const recordAnimationFrames = (callback, autoStart = true) => {
|
|
966
|
+
let running = true,
|
|
967
|
+
raf;
|
|
968
|
+
const stop = () => {
|
|
969
|
+
running = false;
|
|
970
|
+
cancelAnimationFrame(raf);
|
|
971
|
+
};
|
|
972
|
+
const start = () => {
|
|
973
|
+
running = true;
|
|
974
|
+
run();
|
|
975
|
+
};
|
|
976
|
+
const run = () => {
|
|
977
|
+
raf = requestAnimationFrame(() => {
|
|
978
|
+
callback();
|
|
979
|
+
if (running) run();
|
|
980
|
+
});
|
|
981
|
+
};
|
|
982
|
+
if (autoStart) start();
|
|
983
|
+
return { start, stop };
|
|
984
|
+
};
|
|
985
|
+
const redirect = (url, asLink = true) =>
|
|
986
|
+
asLink ? (window.location.href = url) : window.location.replace(url);
|
|
987
|
+
const reducedFilter = (data, keys, fn) =>
|
|
988
|
+
data.filter(fn).map(el =>
|
|
989
|
+
keys.reduce((acc, key) => {
|
|
990
|
+
acc[key] = el[key];
|
|
991
|
+
return acc;
|
|
992
|
+
}, {})
|
|
993
|
+
);
|
|
994
|
+
const reduceSuccessive = (arr, fn, acc) =>
|
|
995
|
+
arr.reduce((res, val, i, arr) => (res.push(fn(res.slice(-1)[0], val, i, arr)), res), [acc]);
|
|
996
|
+
const reduceWhich = (arr, comparator = (a, b) => a - b) =>
|
|
997
|
+
arr.reduce((a, b) => (comparator(a, b) >= 0 ? b : a));
|
|
998
|
+
const reject = (pred, array) => array.filter((...args) => !pred(...args));
|
|
999
|
+
const remove = (arr, func) =>
|
|
1000
|
+
Array.isArray(arr)
|
|
1001
|
+
? arr.filter(func).reduce((acc, val) => {
|
|
1002
|
+
arr.splice(arr.indexOf(val), 1);
|
|
1003
|
+
return acc.concat(val);
|
|
1004
|
+
}, [])
|
|
1005
|
+
: [];
|
|
1006
|
+
const removeNonASCII = str => str.replace(/[^\x20-\x7E]/g, '');
|
|
1007
|
+
const renameKeys = (keysMap, obj) =>
|
|
1008
|
+
Object.keys(obj).reduce(
|
|
1009
|
+
(acc, key) => ({
|
|
1010
|
+
...acc,
|
|
1011
|
+
...{ [keysMap[key] || key]: obj[key] }
|
|
1012
|
+
}),
|
|
1013
|
+
{}
|
|
1014
|
+
);
|
|
1015
|
+
const reverseString = str => [...str].reverse().join('');
|
|
1016
|
+
const RGBToHex = (r, g, b) => ((r << 16) + (g << 8) + b).toString(16).padStart(6, '0');
|
|
1017
|
+
const round = (n, decimals = 0) => Number(`${Math.round(`${n}e${decimals}`)}e-${decimals}`);
|
|
1018
|
+
const runAsync = fn => {
|
|
1019
|
+
const worker = new Worker(
|
|
1020
|
+
URL.createObjectURL(new Blob([`postMessage((${fn})());`]), {
|
|
1021
|
+
type: 'application/javascript; charset=utf-8'
|
|
1022
|
+
})
|
|
1023
|
+
);
|
|
1024
|
+
return new Promise((res, rej) => {
|
|
1025
|
+
worker.onmessage = ({ data }) => {
|
|
1026
|
+
res(data), worker.terminate();
|
|
1027
|
+
};
|
|
1028
|
+
worker.onerror = err => {
|
|
1029
|
+
rej(err), worker.terminate();
|
|
1030
|
+
};
|
|
1031
|
+
});
|
|
1032
|
+
};
|
|
1033
|
+
const runPromisesInSeries = ps => ps.reduce((p, next) => p.then(next), Promise.resolve());
|
|
1034
|
+
const sample = arr => arr[Math.floor(Math.random() * arr.length)];
|
|
1035
|
+
const sampleSize = ([...arr], n = 1) => {
|
|
1036
|
+
let m = arr.length;
|
|
1037
|
+
while (m) {
|
|
1038
|
+
const i = Math.floor(Math.random() * m--);
|
|
1039
|
+
[arr[m], arr[i]] = [arr[i], arr[m]];
|
|
1040
|
+
}
|
|
1041
|
+
return arr.slice(0, n);
|
|
1042
|
+
};
|
|
1043
|
+
const scrollToTop = () => {
|
|
1044
|
+
const c = document.documentElement.scrollTop || document.body.scrollTop;
|
|
1045
|
+
if (c > 0) {
|
|
1046
|
+
window.requestAnimationFrame(scrollToTop);
|
|
1047
|
+
window.scrollTo(0, c - c / 8);
|
|
1048
|
+
}
|
|
1049
|
+
};
|
|
1050
|
+
const sdbm = str => {
|
|
1051
|
+
let arr = str.split('');
|
|
1052
|
+
return arr.reduce(
|
|
1053
|
+
(hashCode, currentVal) =>
|
|
1054
|
+
(hashCode = currentVal.charCodeAt(0) + (hashCode << 6) + (hashCode << 16) - hashCode),
|
|
1055
|
+
0
|
|
1056
|
+
);
|
|
1057
|
+
};
|
|
1058
|
+
const serializeCookie = (name, val) => `${encodeURIComponent(name)}=${encodeURIComponent(val)}`;
|
|
1059
|
+
const serializeForm = form =>
|
|
1060
|
+
Array.from(new FormData(form), field => field.map(encodeURIComponent).join('=')).join('&');
|
|
1061
|
+
const setStyle = (el, ruleName, val) => (el.style[ruleName] = val);
|
|
1062
|
+
const shallowClone = obj => Object.assign({}, obj);
|
|
1063
|
+
const shank = (arr, index = 0, delCount = 0, ...elements) =>
|
|
1064
|
+
arr
|
|
1065
|
+
.slice(0, index)
|
|
1066
|
+
.concat(elements)
|
|
1067
|
+
.concat(arr.slice(index + delCount));
|
|
1068
|
+
const show = (...el) => [...el].forEach(e => (e.style.display = ''));
|
|
1069
|
+
const shuffle = ([...arr]) => {
|
|
1070
|
+
let m = arr.length;
|
|
1071
|
+
while (m) {
|
|
1072
|
+
const i = Math.floor(Math.random() * m--);
|
|
1073
|
+
[arr[m], arr[i]] = [arr[i], arr[m]];
|
|
1074
|
+
}
|
|
1075
|
+
return arr;
|
|
1076
|
+
};
|
|
1077
|
+
const similarity = (arr, values) => arr.filter(v => values.includes(v));
|
|
1078
|
+
const size = val =>
|
|
1079
|
+
Array.isArray(val)
|
|
1080
|
+
? val.length
|
|
1081
|
+
: val && typeof val === 'object'
|
|
1082
|
+
? val.size || val.length || Object.keys(val).length
|
|
1083
|
+
: typeof val === 'string'
|
|
1084
|
+
? new Blob([val]).size
|
|
1085
|
+
: 0;
|
|
1086
|
+
const sleep = ms => new Promise(resolve => setTimeout(resolve, ms));
|
|
1087
|
+
const smoothScroll = element =>
|
|
1088
|
+
document.querySelector(element).scrollIntoView({
|
|
1089
|
+
behavior: 'smooth'
|
|
1090
|
+
});
|
|
1091
|
+
const sortCharactersInString = str => [...str].sort((a, b) => a.localeCompare(b)).join('');
|
|
1092
|
+
const sortedIndex = (arr, n) => {
|
|
1093
|
+
const isDescending = arr[0] > arr[arr.length - 1];
|
|
1094
|
+
const index = arr.findIndex(el => (isDescending ? n >= el : n <= el));
|
|
1095
|
+
return index === -1 ? arr.length : index;
|
|
1096
|
+
};
|
|
1097
|
+
const sortedIndexBy = (arr, n, fn) => {
|
|
1098
|
+
const isDescending = fn(arr[0]) > fn(arr[arr.length - 1]);
|
|
1099
|
+
const val = fn(n);
|
|
1100
|
+
const index = arr.findIndex(el => (isDescending ? val >= fn(el) : val <= fn(el)));
|
|
1101
|
+
return index === -1 ? arr.length : index;
|
|
1102
|
+
};
|
|
1103
|
+
const sortedLastIndex = (arr, n) => {
|
|
1104
|
+
const isDescending = arr[0] > arr[arr.length - 1];
|
|
1105
|
+
const index = arr.reverse().findIndex(el => (isDescending ? n <= el : n >= el));
|
|
1106
|
+
return index === -1 ? 0 : arr.length - index;
|
|
1107
|
+
};
|
|
1108
|
+
const sortedLastIndexBy = (arr, n, fn) => {
|
|
1109
|
+
const isDescending = fn(arr[0]) > fn(arr[arr.length - 1]);
|
|
1110
|
+
const val = fn(n);
|
|
1111
|
+
const index = arr
|
|
1112
|
+
.map(fn)
|
|
1113
|
+
.reverse()
|
|
1114
|
+
.findIndex(el => (isDescending ? val <= el : val >= el));
|
|
1115
|
+
return index === -1 ? 0 : arr.length - index;
|
|
1116
|
+
};
|
|
1117
|
+
const splitLines = str => str.split(/\r?\n/);
|
|
1118
|
+
const spreadOver = fn => argsArr => fn(...argsArr);
|
|
1119
|
+
const stableSort = (arr, compare) =>
|
|
1120
|
+
arr
|
|
1121
|
+
.map((item, index) => ({ item, index }))
|
|
1122
|
+
.sort((a, b) => compare(a.item, b.item) || a.index - b.index)
|
|
1123
|
+
.map(({ item }) => item);
|
|
1124
|
+
const standardDeviation = (arr, usePopulation = false) => {
|
|
1125
|
+
const mean = arr.reduce((acc, val) => acc + val, 0) / arr.length;
|
|
1126
|
+
return Math.sqrt(
|
|
1127
|
+
arr.reduce((acc, val) => acc.concat((val - mean) ** 2), []).reduce((acc, val) => acc + val, 0) /
|
|
1128
|
+
(arr.length - (usePopulation ? 0 : 1))
|
|
1129
|
+
);
|
|
1130
|
+
};
|
|
1131
|
+
const stringPermutations = str => {
|
|
1132
|
+
if (str.length <= 2) return str.length === 2 ? [str, str[1] + str[0]] : [str];
|
|
1133
|
+
return str
|
|
1134
|
+
.split('')
|
|
1135
|
+
.reduce(
|
|
1136
|
+
(acc, letter, i) =>
|
|
1137
|
+
acc.concat(stringPermutations(str.slice(0, i) + str.slice(i + 1)).map(val => letter + val)),
|
|
1138
|
+
[]
|
|
1139
|
+
);
|
|
1140
|
+
};
|
|
1141
|
+
const stripHTMLTags = str => str.replace(/<[^>]*>/g, '');
|
|
1142
|
+
const sum = (...arr) => [...arr].reduce((acc, val) => acc + val, 0);
|
|
1143
|
+
const sumBy = (arr, fn) =>
|
|
1144
|
+
arr.map(typeof fn === 'function' ? fn : val => val[fn]).reduce((acc, val) => acc + val, 0);
|
|
1145
|
+
const sumPower = (end, power = 2, start = 1) =>
|
|
1146
|
+
Array(end + 1 - start)
|
|
1147
|
+
.fill(0)
|
|
1148
|
+
.map((x, i) => (i + start) ** power)
|
|
1149
|
+
.reduce((a, b) => a + b, 0);
|
|
1150
|
+
const symmetricDifference = (a, b) => {
|
|
1151
|
+
const sA = new Set(a),
|
|
1152
|
+
sB = new Set(b);
|
|
1153
|
+
return [...a.filter(x => !sB.has(x)), ...b.filter(x => !sA.has(x))];
|
|
1154
|
+
};
|
|
1155
|
+
const symmetricDifferenceBy = (a, b, fn) => {
|
|
1156
|
+
const sA = new Set(a.map(v => fn(v))),
|
|
1157
|
+
sB = new Set(b.map(v => fn(v)));
|
|
1158
|
+
return [...a.filter(x => !sB.has(fn(x))), ...b.filter(x => !sA.has(fn(x)))];
|
|
1159
|
+
};
|
|
1160
|
+
const symmetricDifferenceWith = (arr, val, comp) => [
|
|
1161
|
+
...arr.filter(a => val.findIndex(b => comp(a, b)) === -1),
|
|
1162
|
+
...val.filter(a => arr.findIndex(b => comp(a, b)) === -1)
|
|
1163
|
+
];
|
|
1164
|
+
const tail = arr => (arr.length > 1 ? arr.slice(1) : arr);
|
|
1165
|
+
const take = (arr, n = 1) => arr.slice(0, n);
|
|
1166
|
+
const takeRight = (arr, n = 1) => arr.slice(arr.length - n, arr.length);
|
|
1167
|
+
const takeRightWhile = (arr, func) =>
|
|
1168
|
+
arr.reduceRight((acc, el) => (func(el) ? acc : [el, ...acc]), []);
|
|
1169
|
+
const takeWhile = (arr, func) => {
|
|
1170
|
+
for (const [i, val] of arr.entries()) if (func(val)) return arr.slice(0, i);
|
|
1171
|
+
return arr;
|
|
1172
|
+
};
|
|
1173
|
+
const throttle = (fn, wait) => {
|
|
1174
|
+
let inThrottle, lastFn, lastTime;
|
|
1175
|
+
return function() {
|
|
1176
|
+
const context = this,
|
|
1177
|
+
args = arguments;
|
|
1178
|
+
if (!inThrottle) {
|
|
1179
|
+
fn.apply(context, args);
|
|
1180
|
+
lastTime = Date.now();
|
|
1181
|
+
inThrottle = true;
|
|
1182
|
+
} else {
|
|
1183
|
+
clearTimeout(lastFn);
|
|
1184
|
+
lastFn = setTimeout(function() {
|
|
1185
|
+
if (Date.now() - lastTime >= wait) {
|
|
1186
|
+
fn.apply(context, args);
|
|
1187
|
+
lastTime = Date.now();
|
|
1188
|
+
}
|
|
1189
|
+
}, Math.max(wait - (Date.now() - lastTime), 0));
|
|
1190
|
+
}
|
|
1191
|
+
};
|
|
1192
|
+
};
|
|
1193
|
+
const times = (n, fn, context = undefined) => {
|
|
1194
|
+
let i = 0;
|
|
1195
|
+
while (fn.call(context, i) !== false && ++i < n) {}
|
|
1196
|
+
};
|
|
1197
|
+
const timeTaken = callback => {
|
|
1198
|
+
console.time('timeTaken');
|
|
1199
|
+
const r = callback();
|
|
1200
|
+
console.timeEnd('timeTaken');
|
|
1201
|
+
return r;
|
|
1202
|
+
};
|
|
1203
|
+
const toCamelCase = str => {
|
|
1204
|
+
let s =
|
|
1205
|
+
str &&
|
|
1206
|
+
str
|
|
1207
|
+
.match(/[A-Z]{2,}(?=[A-Z][a-z]+[0-9]*|\b)|[A-Z]?[a-z]+[0-9]*|[A-Z]|[0-9]+/g)
|
|
1208
|
+
.map(x => x.slice(0, 1).toUpperCase() + x.slice(1).toLowerCase())
|
|
1209
|
+
.join('');
|
|
1210
|
+
return s.slice(0, 1).toLowerCase() + s.slice(1);
|
|
1211
|
+
};
|
|
1212
|
+
const toCurrency = (n, curr, LanguageFormat = undefined) =>
|
|
1213
|
+
Intl.NumberFormat(LanguageFormat, { style: 'currency', currency: curr }).format(n);
|
|
1214
|
+
const toDecimalMark = num => num.toLocaleString('en-US');
|
|
1215
|
+
const toggleClass = (el, className) => el.classList.toggle(className);
|
|
1216
|
+
const toHash = (object, key) =>
|
|
1217
|
+
Array.prototype.reduce.call(
|
|
1218
|
+
object,
|
|
1219
|
+
(acc, data, index) => ((acc[!key ? index : data[key]] = data), acc),
|
|
1220
|
+
{}
|
|
1221
|
+
);
|
|
1222
|
+
const toKebabCase = str =>
|
|
1223
|
+
str &&
|
|
1224
|
+
str
|
|
1225
|
+
.match(/[A-Z]{2,}(?=[A-Z][a-z]+[0-9]*|\b)|[A-Z]?[a-z]+[0-9]*|[A-Z]|[0-9]+/g)
|
|
1226
|
+
.map(x => x.toLowerCase())
|
|
1227
|
+
.join('-');
|
|
1228
|
+
const tomorrow = () => {
|
|
1229
|
+
let t = new Date();
|
|
1230
|
+
t.setDate(t.getDate() + 1);
|
|
1231
|
+
return t.toISOString().split('T')[0];
|
|
1232
|
+
};
|
|
1233
|
+
const toOrdinalSuffix = num => {
|
|
1234
|
+
const int = parseInt(num),
|
|
1235
|
+
digits = [int % 10, int % 100],
|
|
1236
|
+
ordinals = ['st', 'nd', 'rd', 'th'],
|
|
1237
|
+
oPattern = [1, 2, 3, 4],
|
|
1238
|
+
tPattern = [11, 12, 13, 14, 15, 16, 17, 18, 19];
|
|
1239
|
+
return oPattern.includes(digits[0]) && !tPattern.includes(digits[1])
|
|
1240
|
+
? int + ordinals[digits[0] - 1]
|
|
1241
|
+
: int + ordinals[3];
|
|
1242
|
+
};
|
|
1243
|
+
const toSafeInteger = num =>
|
|
1244
|
+
Math.round(Math.max(Math.min(num, Number.MAX_SAFE_INTEGER), Number.MIN_SAFE_INTEGER));
|
|
1245
|
+
const toSnakeCase = str =>
|
|
1246
|
+
str &&
|
|
1247
|
+
str
|
|
1248
|
+
.match(/[A-Z]{2,}(?=[A-Z][a-z]+[0-9]*|\b)|[A-Z]?[a-z]+[0-9]*|[A-Z]|[0-9]+/g)
|
|
1249
|
+
.map(x => x.toLowerCase())
|
|
1250
|
+
.join('_');
|
|
1251
|
+
const toTitleCase = str =>
|
|
1252
|
+
str
|
|
1253
|
+
.match(/[A-Z]{2,}(?=[A-Z][a-z]+[0-9]*|\b)|[A-Z]?[a-z]+[0-9]*|[A-Z]|[0-9]+/g)
|
|
1254
|
+
.map(x => x.charAt(0).toUpperCase() + x.slice(1))
|
|
1255
|
+
.join(' ');
|
|
1256
|
+
const transform = (obj, fn, acc) => Object.keys(obj).reduce((a, k) => fn(a, obj[k], k, obj), acc);
|
|
1257
|
+
const triggerEvent = (el, eventType, detail) =>
|
|
1258
|
+
el.dispatchEvent(new CustomEvent(eventType, { detail }));
|
|
1259
|
+
const truncateString = (str, num) =>
|
|
1260
|
+
str.length > num ? str.slice(0, num > 3 ? num - 3 : num) + '...' : str;
|
|
1261
|
+
const truthCheckCollection = (collection, pre) => collection.every(obj => obj[pre]);
|
|
1262
|
+
const unary = fn => val => fn(val);
|
|
1263
|
+
const uncurry = (fn, n = 1) => (...args) => {
|
|
1264
|
+
const next = acc => args => args.reduce((x, y) => x(y), acc);
|
|
1265
|
+
if (n > args.length) throw new RangeError('Arguments too few!');
|
|
1266
|
+
return next(fn)(args.slice(0, n));
|
|
1267
|
+
};
|
|
1268
|
+
const unescapeHTML = str =>
|
|
1269
|
+
str.replace(
|
|
1270
|
+
/&|<|>|'|"/g,
|
|
1271
|
+
tag =>
|
|
1272
|
+
({
|
|
1273
|
+
'&': '&',
|
|
1274
|
+
'<': '<',
|
|
1275
|
+
'>': '>',
|
|
1276
|
+
''': "'",
|
|
1277
|
+
'"': '"'
|
|
1278
|
+
}[tag] || tag)
|
|
1279
|
+
);
|
|
1280
|
+
const unflattenObject = obj =>
|
|
1281
|
+
Object.keys(obj).reduce((acc, k) => {
|
|
1282
|
+
if (k.indexOf('.') !== -1) {
|
|
1283
|
+
const keys = k.split('.');
|
|
1284
|
+
Object.assign(
|
|
1285
|
+
acc,
|
|
1286
|
+
JSON.parse(
|
|
1287
|
+
'{' +
|
|
1288
|
+
keys.map((v, i) => (i !== keys.length - 1 ? `"${v}":{` : `"${v}":`)).join('') +
|
|
1289
|
+
obj[k] +
|
|
1290
|
+
'}'.repeat(keys.length)
|
|
1291
|
+
)
|
|
1292
|
+
);
|
|
1293
|
+
} else acc[k] = obj[k];
|
|
1294
|
+
return acc;
|
|
1295
|
+
}, {});
|
|
1296
|
+
const unfold = (fn, seed) => {
|
|
1297
|
+
let result = [],
|
|
1298
|
+
val = [null, seed];
|
|
1299
|
+
while ((val = fn(val[1]))) result.push(val[0]);
|
|
1300
|
+
return result;
|
|
1301
|
+
};
|
|
1302
|
+
const union = (a, b) => Array.from(new Set([...a, ...b]));
|
|
1303
|
+
const unionBy = (a, b, fn) => {
|
|
1304
|
+
const s = new Set(a.map(fn));
|
|
1305
|
+
return Array.from(new Set([...a, ...b.filter(x => !s.has(fn(x)))]));
|
|
1306
|
+
};
|
|
1307
|
+
const unionWith = (a, b, comp) =>
|
|
1308
|
+
Array.from(new Set([...a, ...b.filter(x => a.findIndex(y => comp(x, y)) === -1)]));
|
|
1309
|
+
const uniqueElements = arr => [...new Set(arr)];
|
|
1310
|
+
const uniqueElementsBy = (arr, fn) =>
|
|
1311
|
+
arr.reduce((acc, v) => {
|
|
1312
|
+
if (!acc.some(x => fn(v, x))) acc.push(v);
|
|
1313
|
+
return acc;
|
|
1314
|
+
}, []);
|
|
1315
|
+
const uniqueElementsByRight = (arr, fn) =>
|
|
1316
|
+
arr.reduceRight((acc, v) => {
|
|
1317
|
+
if (!acc.some(x => fn(v, x))) acc.push(v);
|
|
1318
|
+
return acc;
|
|
1319
|
+
}, []);
|
|
1320
|
+
const uniqueSymmetricDifference = (a, b) => [
|
|
1321
|
+
...new Set([...a.filter(v => !b.includes(v)), ...b.filter(v => !a.includes(v))])
|
|
1322
|
+
];
|
|
1323
|
+
const untildify = str => str.replace(/^~($|\/|\\)/, `${require('os').homedir()}$1`);
|
|
1324
|
+
const unzip = arr =>
|
|
1325
|
+
arr.reduce(
|
|
1326
|
+
(acc, val) => (val.forEach((v, i) => acc[i].push(v)), acc),
|
|
1327
|
+
Array.from({
|
|
1328
|
+
length: Math.max(...arr.map(x => x.length))
|
|
1329
|
+
}).map(x => [])
|
|
1330
|
+
);
|
|
1331
|
+
const unzipWith = (arr, fn) =>
|
|
1332
|
+
arr
|
|
1333
|
+
.reduce(
|
|
1334
|
+
(acc, val) => (val.forEach((v, i) => acc[i].push(v)), acc),
|
|
1335
|
+
Array.from({
|
|
1336
|
+
length: Math.max(...arr.map(x => x.length))
|
|
1337
|
+
}).map(x => [])
|
|
1338
|
+
)
|
|
1339
|
+
.map(val => fn(...val));
|
|
1340
|
+
const URLJoin = (...args) =>
|
|
1341
|
+
args
|
|
1342
|
+
.join('/')
|
|
1343
|
+
.replace(/[\/]+/g, '/')
|
|
1344
|
+
.replace(/^(.+):\//, '$1://')
|
|
1345
|
+
.replace(/^file:/, 'file:/')
|
|
1346
|
+
.replace(/\/(\?|&|#[^!])/g, '$1')
|
|
1347
|
+
.replace(/\?/g, '&')
|
|
1348
|
+
.replace('&', '?');
|
|
1349
|
+
const UUIDGeneratorBrowser = () =>
|
|
1350
|
+
([1e7] + -1e3 + -4e3 + -8e3 + -1e11).replace(/[018]/g, c =>
|
|
1351
|
+
(c ^ (crypto.getRandomValues(new Uint8Array(1))[0] & (15 >> (c / 4)))).toString(16)
|
|
1352
|
+
);
|
|
1353
|
+
const UUIDGeneratorNode = () =>
|
|
1354
|
+
([1e7] + -1e3 + -4e3 + -8e3 + -1e11).replace(/[018]/g, c =>
|
|
1355
|
+
(c ^ (crypto.randomBytes(1)[0] & (15 >> (c / 4)))).toString(16)
|
|
1356
|
+
);
|
|
1357
|
+
const validateNumber = n => !isNaN(parseFloat(n)) && isFinite(n) && Number(n) == n;
|
|
1358
|
+
const vectorDistance = (...coords) => {
|
|
1359
|
+
let pointLength = Math.trunc(coords.length / 2);
|
|
1360
|
+
let sum = coords
|
|
1361
|
+
.slice(0, pointLength)
|
|
1362
|
+
.reduce((acc, val, i) => acc + Math.pow(val - coords[pointLength + i], 2), 0);
|
|
1363
|
+
return Math.sqrt(sum);
|
|
1364
|
+
};
|
|
1365
|
+
const when = (pred, whenTrue) => x => (pred(x) ? whenTrue(x) : x);
|
|
1366
|
+
const without = (arr, ...args) => arr.filter(v => !args.includes(v));
|
|
1367
|
+
const words = (str, pattern = /[^a-zA-Z-]+/) => str.split(pattern).filter(Boolean);
|
|
1368
|
+
const xProd = (a, b) => a.reduce((acc, x) => acc.concat(b.map(y => [x, y])), []);
|
|
1369
|
+
const yesNo = (val, def = false) =>
|
|
1370
|
+
/^(y|yes)$/i.test(val) ? true : /^(n|no)$/i.test(val) ? false : def;
|
|
1371
|
+
const yesterday = () => {
|
|
1372
|
+
let t = new Date();
|
|
1373
|
+
t.setDate(t.getDate() - 1);
|
|
1374
|
+
return t.toISOString().split('T')[0];
|
|
1375
|
+
};
|
|
1376
|
+
const zip = (...arrays) => {
|
|
1377
|
+
const maxLength = Math.max(...arrays.map(x => x.length));
|
|
1378
|
+
return Array.from({ length: maxLength }).map((_, i) => {
|
|
1379
|
+
return Array.from({ length: arrays.length }, (_, k) => arrays[k][i]);
|
|
1380
|
+
});
|
|
1381
|
+
};
|
|
1382
|
+
const zipObject = (props, values) =>
|
|
1383
|
+
props.reduce((obj, prop, index) => ((obj[prop] = values[index]), obj), {});
|
|
1384
|
+
const zipWith = (...array) => {
|
|
1385
|
+
const fn = typeof array[array.length - 1] === 'function' ? array.pop() : undefined;
|
|
1386
|
+
return Array.from({ length: Math.max(...array.map(a => a.length)) }, (_, i) =>
|
|
1387
|
+
fn ? fn(...array.map(a => a[i])) : array.map(a => a[i])
|
|
1388
|
+
);
|
|
1389
|
+
};
|
|
1390
|
+
const binarySearch = (arr, val, start = 0, end = arr.length - 1) => {
|
|
1391
|
+
if (start > end) return -1;
|
|
1392
|
+
const mid = Math.floor((start + end) / 2);
|
|
1393
|
+
if (arr[mid] > val) return binarySearch(arr, val, start, mid - 1);
|
|
1394
|
+
if (arr[mid] < val) return binarySearch(arr, val, mid + 1, end);
|
|
1395
|
+
return mid;
|
|
1396
|
+
};
|
|
1397
|
+
const celsiusToFahrenheit = degrees => 1.8 * degrees + 32;
|
|
1398
|
+
const cleanObj = (obj, keysToKeep = [], childIndicator) => {
|
|
1399
|
+
Object.keys(obj).forEach(key => {
|
|
1400
|
+
if (key === childIndicator) {
|
|
1401
|
+
cleanObj(obj[key], keysToKeep, childIndicator);
|
|
1402
|
+
} else if (!keysToKeep.includes(key)) {
|
|
1403
|
+
delete obj[key];
|
|
1404
|
+
}
|
|
1405
|
+
});
|
|
1406
|
+
return obj;
|
|
1407
|
+
};
|
|
1408
|
+
const collatz = n => (n % 2 === 0 ? n / 2 : 3 * n + 1);
|
|
1409
|
+
const countVowels = str => (str.match(/[aeiou]/gi) || []).length;
|
|
1410
|
+
const factors = (num, primes = false) => {
|
|
1411
|
+
const isPrime = num => {
|
|
1412
|
+
const boundary = Math.floor(Math.sqrt(num));
|
|
1413
|
+
for (var i = 2; i <= boundary; i++) if (num % i === 0) return false;
|
|
1414
|
+
return num >= 2;
|
|
1415
|
+
};
|
|
1416
|
+
const isNeg = num < 0;
|
|
1417
|
+
num = isNeg ? -num : num;
|
|
1418
|
+
let array = Array.from({ length: num - 1 })
|
|
1419
|
+
.map((val, i) => (num % (i + 2) === 0 ? i + 2 : false))
|
|
1420
|
+
.filter(val => val);
|
|
1421
|
+
if (isNeg)
|
|
1422
|
+
array = array.reduce((acc, val) => {
|
|
1423
|
+
acc.push(val);
|
|
1424
|
+
acc.push(-val);
|
|
1425
|
+
return acc;
|
|
1426
|
+
}, []);
|
|
1427
|
+
return primes ? array.filter(isPrime) : array;
|
|
1428
|
+
};
|
|
1429
|
+
const fahrenheitToCelsius = degrees => (degrees - 32) * 5/9;
|
|
1430
|
+
const fibonacciCountUntilNum = num =>
|
|
1431
|
+
Math.ceil(Math.log(num * Math.sqrt(5) + 1 / 2) / Math.log((Math.sqrt(5) + 1) / 2));
|
|
1432
|
+
const fibonacciUntilNum = num => {
|
|
1433
|
+
let n = Math.ceil(Math.log(num * Math.sqrt(5) + 1 / 2) / Math.log((Math.sqrt(5) + 1) / 2));
|
|
1434
|
+
return Array.from({ length: n }).reduce(
|
|
1435
|
+
(acc, val, i) => acc.concat(i > 1 ? acc[i - 1] + acc[i - 2] : i),
|
|
1436
|
+
[]
|
|
1437
|
+
);
|
|
1438
|
+
};
|
|
1439
|
+
const heronArea = (side_a, side_b, side_c) => {
|
|
1440
|
+
const p = (side_a + side_b + side_c) / 2;
|
|
1441
|
+
return Math.sqrt(p * (p-side_a) * (p-side_b) * (p-side_c))
|
|
1442
|
+
};
|
|
1443
|
+
const howManyTimes = (num, divisor) => {
|
|
1444
|
+
if (divisor === 1 || divisor === -1) return Infinity;
|
|
1445
|
+
if (divisor === 0) return 0;
|
|
1446
|
+
let i = 0;
|
|
1447
|
+
while (Number.isInteger(num / divisor)) {
|
|
1448
|
+
i++;
|
|
1449
|
+
num = num / divisor;
|
|
1450
|
+
}
|
|
1451
|
+
return i;
|
|
1452
|
+
};
|
|
1453
|
+
const httpDelete = (url, callback, err = console.error) => {
|
|
1454
|
+
const request = new XMLHttpRequest();
|
|
1455
|
+
request.open('DELETE', url, true);
|
|
1456
|
+
request.onload = () => callback(request);
|
|
1457
|
+
request.onerror = () => err(request);
|
|
1458
|
+
request.send();
|
|
1459
|
+
};
|
|
1460
|
+
const httpPut = (url, data, callback, err = console.error) => {
|
|
1461
|
+
const request = new XMLHttpRequest();
|
|
1462
|
+
request.open("PUT", url, true);
|
|
1463
|
+
request.setRequestHeader('Content-type','application/json; charset=utf-8');
|
|
1464
|
+
request.onload = () => callback(request);
|
|
1465
|
+
request.onerror = () => err(request);
|
|
1466
|
+
request.send(data);
|
|
1467
|
+
};
|
|
1468
|
+
const isArmstrongNumber = digits =>
|
|
1469
|
+
(arr => arr.reduce((a, d) => a + parseInt(d) ** arr.length, 0) == digits)(
|
|
1470
|
+
(digits + '').split('')
|
|
1471
|
+
);
|
|
1472
|
+
const isSimilar = (pattern, str) =>
|
|
1473
|
+
[...str].reduce(
|
|
1474
|
+
(matchIndex, char) =>
|
|
1475
|
+
char.toLowerCase() === (pattern[matchIndex] || '').toLowerCase()
|
|
1476
|
+
? matchIndex + 1
|
|
1477
|
+
: matchIndex,
|
|
1478
|
+
0
|
|
1479
|
+
) === pattern.length;
|
|
1480
|
+
const JSONToDate = arr => {
|
|
1481
|
+
const dt = new Date(parseInt(arr.toString().substr(6)));
|
|
1482
|
+
return `${dt.getDate()}/${dt.getMonth() + 1}/${dt.getFullYear()}`;
|
|
1483
|
+
};
|
|
1484
|
+
const kmphToMph = (kmph) => 0.621371192 * kmph;
|
|
1485
|
+
const levenshteinDistance = (string1, string2) => {
|
|
1486
|
+
if (string1.length === 0) return string2.length;
|
|
1487
|
+
if (string2.length === 0) return string1.length;
|
|
1488
|
+
let matrix = Array(string2.length + 1)
|
|
1489
|
+
.fill(0)
|
|
1490
|
+
.map((x, i) => [i]);
|
|
1491
|
+
matrix[0] = Array(string1.length + 1)
|
|
1492
|
+
.fill(0)
|
|
1493
|
+
.map((x, i) => i);
|
|
1494
|
+
for (let i = 1; i <= string2.length; i++) {
|
|
1495
|
+
for (let j = 1; j <= string1.length; j++) {
|
|
1496
|
+
if (string2[i - 1] === string1[j - 1]) {
|
|
1497
|
+
matrix[i][j] = matrix[i - 1][j - 1];
|
|
1498
|
+
} else {
|
|
1499
|
+
matrix[i][j] = Math.min(
|
|
1500
|
+
matrix[i - 1][j - 1] + 1,
|
|
1501
|
+
matrix[i][j - 1] + 1,
|
|
1502
|
+
matrix[i - 1][j] + 1
|
|
1503
|
+
);
|
|
1504
|
+
}
|
|
1505
|
+
}
|
|
1506
|
+
}
|
|
1507
|
+
return matrix[string2.length][string1.length];
|
|
1508
|
+
};
|
|
1509
|
+
const mphToKmph = (mph) => 1.6093440006146922 * mph;
|
|
1510
|
+
const pipeLog = data => console.log(data) || data;
|
|
1511
|
+
const quickSort = ([n, ...nums], desc) =>
|
|
1512
|
+
isNaN(n)
|
|
1513
|
+
? []
|
|
1514
|
+
: [
|
|
1515
|
+
...quickSort(nums.filter(v => (desc ? v > n : v <= n)), desc),
|
|
1516
|
+
n,
|
|
1517
|
+
...quickSort(nums.filter(v => (!desc ? v > n : v <= n)), desc)
|
|
1518
|
+
];
|
|
1519
|
+
const removeVowels = (str, repl = '') => str.replace(/[aeiou]/gi, repl);
|
|
1520
|
+
const solveRPN = rpn => {
|
|
1521
|
+
const OPERATORS = {
|
|
1522
|
+
'*': (a, b) => a * b,
|
|
1523
|
+
'+': (a, b) => a + b,
|
|
1524
|
+
'-': (a, b) => a - b,
|
|
1525
|
+
'/': (a, b) => a / b,
|
|
1526
|
+
'**': (a, b) => a ** b
|
|
1527
|
+
};
|
|
1528
|
+
const [stack, solve] = [
|
|
1529
|
+
[],
|
|
1530
|
+
rpn
|
|
1531
|
+
.replace(/\^/g, '**')
|
|
1532
|
+
.split(/\s+/g)
|
|
1533
|
+
.filter(el => !/\s+/.test(el) && el !== '')
|
|
1534
|
+
];
|
|
1535
|
+
solve.forEach(symbol => {
|
|
1536
|
+
if (!isNaN(parseFloat(symbol)) && isFinite(symbol)) {
|
|
1537
|
+
stack.push(symbol);
|
|
1538
|
+
} else if (Object.keys(OPERATORS).includes(symbol)) {
|
|
1539
|
+
const [a, b] = [stack.pop(), stack.pop()];
|
|
1540
|
+
stack.push(OPERATORS[symbol](parseFloat(b), parseFloat(a)));
|
|
1541
|
+
} else {
|
|
1542
|
+
throw `${symbol} is not a recognized symbol`;
|
|
1543
|
+
}
|
|
1544
|
+
});
|
|
1545
|
+
if (stack.length === 1) return stack.pop();
|
|
1546
|
+
else throw `${rpn} is not a proper RPN. Please check it and try again`;
|
|
1547
|
+
};
|
|
1548
|
+
const speechSynthesis = message => {
|
|
1549
|
+
const msg = new SpeechSynthesisUtterance(message);
|
|
1550
|
+
msg.voice = window.speechSynthesis.getVoices()[0];
|
|
1551
|
+
window.speechSynthesis.speak(msg);
|
|
1552
|
+
};
|
|
1553
|
+
const squareSum = (...args) => args.reduce((squareSum, number) => squareSum + Math.pow(number, 2), 0);
|
|
1554
|
+
const exports={}
|
|
1555
|
+
exports.all = all;
|
|
1556
|
+
exports.allEqual = allEqual;
|
|
1557
|
+
exports.any = any;
|
|
1558
|
+
exports.approximatelyEqual = approximatelyEqual;
|
|
1559
|
+
exports.arrayToCSV = arrayToCSV;
|
|
1560
|
+
exports.arrayToHtmlList = arrayToHtmlList;
|
|
1561
|
+
exports.ary = ary;
|
|
1562
|
+
exports.atob = atob;
|
|
1563
|
+
exports.attempt = attempt;
|
|
1564
|
+
exports.average = average;
|
|
1565
|
+
exports.averageBy = averageBy;
|
|
1566
|
+
exports.bifurcate = bifurcate;
|
|
1567
|
+
exports.bifurcateBy = bifurcateBy;
|
|
1568
|
+
exports.bind = bind;
|
|
1569
|
+
exports.bindAll = bindAll;
|
|
1570
|
+
exports.bindKey = bindKey;
|
|
1571
|
+
exports.binomialCoefficient = binomialCoefficient;
|
|
1572
|
+
exports.bottomVisible = bottomVisible;
|
|
1573
|
+
exports.btoa = btoa;
|
|
1574
|
+
exports.byteSize = byteSize;
|
|
1575
|
+
exports.call = call;
|
|
1576
|
+
exports.capitalize = capitalize;
|
|
1577
|
+
exports.capitalizeEveryWord = capitalizeEveryWord;
|
|
1578
|
+
exports.castArray = castArray;
|
|
1579
|
+
exports.chainAsync = chainAsync;
|
|
1580
|
+
exports.checkProp = checkProp;
|
|
1581
|
+
exports.chunk = chunk;
|
|
1582
|
+
exports.clampNumber = clampNumber;
|
|
1583
|
+
exports.cloneRegExp = cloneRegExp;
|
|
1584
|
+
exports.coalesce = coalesce;
|
|
1585
|
+
exports.coalesceFactory = coalesceFactory;
|
|
1586
|
+
exports.collectInto = collectInto;
|
|
1587
|
+
exports.colorize = colorize;
|
|
1588
|
+
exports.compact = compact;
|
|
1589
|
+
exports.compactWhitespace = compactWhitespace;
|
|
1590
|
+
exports.compose = compose;
|
|
1591
|
+
exports.composeRight = composeRight;
|
|
1592
|
+
exports.converge = converge;
|
|
1593
|
+
exports.copyToClipboard = copyToClipboard;
|
|
1594
|
+
exports.countBy = countBy;
|
|
1595
|
+
exports.counter = counter;
|
|
1596
|
+
exports.countOccurrences = countOccurrences;
|
|
1597
|
+
exports.createDirIfNotExists = createDirIfNotExists;
|
|
1598
|
+
exports.createElement = createElement;
|
|
1599
|
+
exports.createEventHub = createEventHub;
|
|
1600
|
+
exports.CSVToArray = CSVToArray;
|
|
1601
|
+
exports.CSVToJSON = CSVToJSON;
|
|
1602
|
+
exports.currentURL = currentURL;
|
|
1603
|
+
exports.curry = curry;
|
|
1604
|
+
exports.dayOfYear = dayOfYear;
|
|
1605
|
+
exports.debounce = debounce;
|
|
1606
|
+
exports.decapitalize = decapitalize;
|
|
1607
|
+
exports.deepClone = deepClone;
|
|
1608
|
+
exports.deepFlatten = deepFlatten;
|
|
1609
|
+
exports.deepFreeze = deepFreeze;
|
|
1610
|
+
exports.deepGet = deepGet;
|
|
1611
|
+
exports.deepMapKeys = deepMapKeys;
|
|
1612
|
+
exports.defaults = defaults;
|
|
1613
|
+
exports.defer = defer;
|
|
1614
|
+
exports.degreesToRads = degreesToRads;
|
|
1615
|
+
exports.delay = delay;
|
|
1616
|
+
exports.detectDeviceType = detectDeviceType;
|
|
1617
|
+
exports.difference = difference;
|
|
1618
|
+
exports.differenceBy = differenceBy;
|
|
1619
|
+
exports.differenceWith = differenceWith;
|
|
1620
|
+
exports.dig = dig;
|
|
1621
|
+
exports.digitize = digitize;
|
|
1622
|
+
exports.distance = distance;
|
|
1623
|
+
exports.drop = drop;
|
|
1624
|
+
exports.dropRight = dropRight;
|
|
1625
|
+
exports.dropRightWhile = dropRightWhile;
|
|
1626
|
+
exports.dropWhile = dropWhile;
|
|
1627
|
+
exports.elementContains = elementContains;
|
|
1628
|
+
exports.elementIsVisibleInViewport = elementIsVisibleInViewport;
|
|
1629
|
+
exports.elo = elo;
|
|
1630
|
+
exports.equals = equals;
|
|
1631
|
+
exports.escapeHTML = escapeHTML;
|
|
1632
|
+
exports.escapeRegExp = escapeRegExp;
|
|
1633
|
+
exports.everyNth = everyNth;
|
|
1634
|
+
exports.extendHex = extendHex;
|
|
1635
|
+
exports.factorial = factorial;
|
|
1636
|
+
exports.fibonacci = fibonacci;
|
|
1637
|
+
exports.filterFalsy = filterFalsy;
|
|
1638
|
+
exports.filterNonUnique = filterNonUnique;
|
|
1639
|
+
exports.filterNonUniqueBy = filterNonUniqueBy;
|
|
1640
|
+
exports.findKey = findKey;
|
|
1641
|
+
exports.findLast = findLast;
|
|
1642
|
+
exports.findLastIndex = findLastIndex;
|
|
1643
|
+
exports.findLastKey = findLastKey;
|
|
1644
|
+
exports.flatten = flatten;
|
|
1645
|
+
exports.flattenObject = flattenObject;
|
|
1646
|
+
exports.flip = flip;
|
|
1647
|
+
exports.forEachRight = forEachRight;
|
|
1648
|
+
exports.formatDuration = formatDuration;
|
|
1649
|
+
exports.formToObject = formToObject;
|
|
1650
|
+
exports.forOwn = forOwn;
|
|
1651
|
+
exports.forOwnRight = forOwnRight;
|
|
1652
|
+
exports.fromCamelCase = fromCamelCase;
|
|
1653
|
+
exports.functionName = functionName;
|
|
1654
|
+
exports.functions = functions;
|
|
1655
|
+
exports.gcd = gcd;
|
|
1656
|
+
exports.geometricProgression = geometricProgression;
|
|
1657
|
+
exports.get = get;
|
|
1658
|
+
exports.getColonTimeFromDate = getColonTimeFromDate;
|
|
1659
|
+
exports.getDaysDiffBetweenDates = getDaysDiffBetweenDates;
|
|
1660
|
+
exports.getImages = getImages;
|
|
1661
|
+
exports.getMeridiemSuffixOfInteger = getMeridiemSuffixOfInteger;
|
|
1662
|
+
exports.getScrollPosition = getScrollPosition;
|
|
1663
|
+
exports.getStyle = getStyle;
|
|
1664
|
+
exports.getType = getType;
|
|
1665
|
+
exports.getURLParameters = getURLParameters;
|
|
1666
|
+
exports.groupBy = groupBy;
|
|
1667
|
+
exports.hammingDistance = hammingDistance;
|
|
1668
|
+
exports.hasClass = hasClass;
|
|
1669
|
+
exports.hasFlags = hasFlags;
|
|
1670
|
+
exports.hashBrowser = hashBrowser;
|
|
1671
|
+
exports.hashNode = hashNode;
|
|
1672
|
+
exports.head = head;
|
|
1673
|
+
exports.hexToRGB = hexToRGB;
|
|
1674
|
+
exports.hide = hide;
|
|
1675
|
+
exports.httpGet = httpGet;
|
|
1676
|
+
exports.httpPost = httpPost;
|
|
1677
|
+
exports.httpsRedirect = httpsRedirect;
|
|
1678
|
+
exports.hz = hz;
|
|
1679
|
+
exports.indentString = indentString;
|
|
1680
|
+
exports.indexOfAll = indexOfAll;
|
|
1681
|
+
exports.initial = initial;
|
|
1682
|
+
exports.initialize2DArray = initialize2DArray;
|
|
1683
|
+
exports.initializeArrayWithRange = initializeArrayWithRange;
|
|
1684
|
+
exports.initializeArrayWithRangeRight = initializeArrayWithRangeRight;
|
|
1685
|
+
exports.initializeArrayWithValues = initializeArrayWithValues;
|
|
1686
|
+
exports.initializeNDArray = initializeNDArray;
|
|
1687
|
+
exports.inRange = inRange;
|
|
1688
|
+
exports.insertAfter = insertAfter;
|
|
1689
|
+
exports.insertBefore = insertBefore;
|
|
1690
|
+
exports.intersection = intersection;
|
|
1691
|
+
exports.intersectionBy = intersectionBy;
|
|
1692
|
+
exports.intersectionWith = intersectionWith;
|
|
1693
|
+
exports.invertKeyValues = invertKeyValues;
|
|
1694
|
+
exports.is = is;
|
|
1695
|
+
exports.isAbsoluteURL = isAbsoluteURL;
|
|
1696
|
+
exports.isAfterDate = isAfterDate;
|
|
1697
|
+
exports.isAnagram = isAnagram;
|
|
1698
|
+
exports.isArrayLike = isArrayLike;
|
|
1699
|
+
exports.isBeforeDate = isBeforeDate;
|
|
1700
|
+
exports.isBoolean = isBoolean;
|
|
1701
|
+
exports.isBrowser = isBrowser;
|
|
1702
|
+
exports.isBrowserTabFocused = isBrowserTabFocused;
|
|
1703
|
+
exports.isDivisible = isDivisible;
|
|
1704
|
+
exports.isDuplexStream = isDuplexStream;
|
|
1705
|
+
exports.isEmpty = isEmpty;
|
|
1706
|
+
exports.isEven = isEven;
|
|
1707
|
+
exports.isFunction = isFunction;
|
|
1708
|
+
exports.isLowerCase = isLowerCase;
|
|
1709
|
+
exports.isNegativeZero = isNegativeZero;
|
|
1710
|
+
exports.isNil = isNil;
|
|
1711
|
+
exports.isNull = isNull;
|
|
1712
|
+
exports.isNumber = isNumber;
|
|
1713
|
+
exports.isObject = isObject;
|
|
1714
|
+
exports.isObjectLike = isObjectLike;
|
|
1715
|
+
exports.isPlainObject = isPlainObject;
|
|
1716
|
+
exports.isPrime = isPrime;
|
|
1717
|
+
exports.isPrimitive = isPrimitive;
|
|
1718
|
+
exports.isPromiseLike = isPromiseLike;
|
|
1719
|
+
exports.isReadableStream = isReadableStream;
|
|
1720
|
+
exports.isSameDate = isSameDate;
|
|
1721
|
+
exports.isSorted = isSorted;
|
|
1722
|
+
exports.isStream = isStream;
|
|
1723
|
+
exports.isString = isString;
|
|
1724
|
+
exports.isSymbol = isSymbol;
|
|
1725
|
+
exports.isTravisCI = isTravisCI;
|
|
1726
|
+
exports.isUndefined = isUndefined;
|
|
1727
|
+
exports.isUpperCase = isUpperCase;
|
|
1728
|
+
exports.isValidJSON = isValidJSON;
|
|
1729
|
+
exports.isWeekday = isWeekday;
|
|
1730
|
+
exports.isWeekend = isWeekend;
|
|
1731
|
+
exports.isWritableStream = isWritableStream;
|
|
1732
|
+
exports.join = join;
|
|
1733
|
+
exports.JSONtoCSV = JSONtoCSV;
|
|
1734
|
+
exports.JSONToFile = JSONToFile;
|
|
1735
|
+
exports.last = last;
|
|
1736
|
+
exports.lcm = lcm;
|
|
1737
|
+
exports.longestItem = longestItem;
|
|
1738
|
+
exports.lowercaseKeys = lowercaseKeys;
|
|
1739
|
+
exports.luhnCheck = luhnCheck;
|
|
1740
|
+
exports.mapKeys = mapKeys;
|
|
1741
|
+
exports.mapNumRange = mapNumRange;
|
|
1742
|
+
exports.mapObject = mapObject;
|
|
1743
|
+
exports.mapString = mapString;
|
|
1744
|
+
exports.mapValues = mapValues;
|
|
1745
|
+
exports.mask = mask;
|
|
1746
|
+
exports.matches = matches;
|
|
1747
|
+
exports.matchesWith = matchesWith;
|
|
1748
|
+
exports.maxBy = maxBy;
|
|
1749
|
+
exports.maxDate = maxDate;
|
|
1750
|
+
exports.maxN = maxN;
|
|
1751
|
+
exports.median = median;
|
|
1752
|
+
exports.memoize = memoize;
|
|
1753
|
+
exports.merge = merge;
|
|
1754
|
+
exports.midpoint = midpoint;
|
|
1755
|
+
exports.minBy = minBy;
|
|
1756
|
+
exports.minDate = minDate;
|
|
1757
|
+
exports.minN = minN;
|
|
1758
|
+
exports.mostPerformant = mostPerformant;
|
|
1759
|
+
exports.negate = negate;
|
|
1760
|
+
exports.nest = nest;
|
|
1761
|
+
exports.nodeListToArray = nodeListToArray;
|
|
1762
|
+
exports.none = none;
|
|
1763
|
+
exports.nthArg = nthArg;
|
|
1764
|
+
exports.nthElement = nthElement;
|
|
1765
|
+
exports.objectFromPairs = objectFromPairs;
|
|
1766
|
+
exports.objectToPairs = objectToPairs;
|
|
1767
|
+
exports.observeMutations = observeMutations;
|
|
1768
|
+
exports.off = off;
|
|
1769
|
+
exports.offset = offset;
|
|
1770
|
+
exports.omit = omit;
|
|
1771
|
+
exports.omitBy = omitBy;
|
|
1772
|
+
exports.on = on;
|
|
1773
|
+
exports.once = once;
|
|
1774
|
+
exports.onUserInputChange = onUserInputChange;
|
|
1775
|
+
exports.orderBy = orderBy;
|
|
1776
|
+
exports.over = over;
|
|
1777
|
+
exports.overArgs = overArgs;
|
|
1778
|
+
exports.pad = pad;
|
|
1779
|
+
exports.palindrome = palindrome;
|
|
1780
|
+
exports.parseCookie = parseCookie;
|
|
1781
|
+
exports.partial = partial;
|
|
1782
|
+
exports.partialRight = partialRight;
|
|
1783
|
+
exports.partition = partition;
|
|
1784
|
+
exports.percentile = percentile;
|
|
1785
|
+
exports.permutations = permutations;
|
|
1786
|
+
exports.pick = pick;
|
|
1787
|
+
exports.pickBy = pickBy;
|
|
1788
|
+
exports.pipeAsyncFunctions = pipeAsyncFunctions;
|
|
1789
|
+
exports.pipeFunctions = pipeFunctions;
|
|
1790
|
+
exports.pluralize = pluralize;
|
|
1791
|
+
exports.powerset = powerset;
|
|
1792
|
+
exports.prefix = prefix;
|
|
1793
|
+
exports.prettyBytes = prettyBytes;
|
|
1794
|
+
exports.primes = primes;
|
|
1795
|
+
exports.promisify = promisify;
|
|
1796
|
+
exports.pull = pull;
|
|
1797
|
+
exports.pullAtIndex = pullAtIndex;
|
|
1798
|
+
exports.pullAtValue = pullAtValue;
|
|
1799
|
+
exports.pullBy = pullBy;
|
|
1800
|
+
exports.radsToDegrees = radsToDegrees;
|
|
1801
|
+
exports.randomHexColorCode = randomHexColorCode;
|
|
1802
|
+
exports.randomIntArrayInRange = randomIntArrayInRange;
|
|
1803
|
+
exports.randomIntegerInRange = randomIntegerInRange;
|
|
1804
|
+
exports.randomNumberInRange = randomNumberInRange;
|
|
1805
|
+
exports.readFileLines = readFileLines;
|
|
1806
|
+
exports.rearg = rearg;
|
|
1807
|
+
exports.recordAnimationFrames = recordAnimationFrames;
|
|
1808
|
+
exports.redirect = redirect;
|
|
1809
|
+
exports.reducedFilter = reducedFilter;
|
|
1810
|
+
exports.reduceSuccessive = reduceSuccessive;
|
|
1811
|
+
exports.reduceWhich = reduceWhich;
|
|
1812
|
+
exports.reject = reject;
|
|
1813
|
+
exports.remove = remove;
|
|
1814
|
+
exports.removeNonASCII = removeNonASCII;
|
|
1815
|
+
exports.renameKeys = renameKeys;
|
|
1816
|
+
exports.reverseString = reverseString;
|
|
1817
|
+
exports.RGBToHex = RGBToHex;
|
|
1818
|
+
exports.round = round;
|
|
1819
|
+
exports.runAsync = runAsync;
|
|
1820
|
+
exports.runPromisesInSeries = runPromisesInSeries;
|
|
1821
|
+
exports.sample = sample;
|
|
1822
|
+
exports.sampleSize = sampleSize;
|
|
1823
|
+
exports.scrollToTop = scrollToTop;
|
|
1824
|
+
exports.sdbm = sdbm;
|
|
1825
|
+
exports.serializeCookie = serializeCookie;
|
|
1826
|
+
exports.serializeForm = serializeForm;
|
|
1827
|
+
exports.setStyle = setStyle;
|
|
1828
|
+
exports.shallowClone = shallowClone;
|
|
1829
|
+
exports.shank = shank;
|
|
1830
|
+
exports.show = show;
|
|
1831
|
+
exports.shuffle = shuffle;
|
|
1832
|
+
exports.similarity = similarity;
|
|
1833
|
+
exports.size = size;
|
|
1834
|
+
exports.sleep = sleep;
|
|
1835
|
+
exports.smoothScroll = smoothScroll;
|
|
1836
|
+
exports.sortCharactersInString = sortCharactersInString;
|
|
1837
|
+
exports.sortedIndex = sortedIndex;
|
|
1838
|
+
exports.sortedIndexBy = sortedIndexBy;
|
|
1839
|
+
exports.sortedLastIndex = sortedLastIndex;
|
|
1840
|
+
exports.sortedLastIndexBy = sortedLastIndexBy;
|
|
1841
|
+
exports.splitLines = splitLines;
|
|
1842
|
+
exports.spreadOver = spreadOver;
|
|
1843
|
+
exports.stableSort = stableSort;
|
|
1844
|
+
exports.standardDeviation = standardDeviation;
|
|
1845
|
+
exports.stringPermutations = stringPermutations;
|
|
1846
|
+
exports.stripHTMLTags = stripHTMLTags;
|
|
1847
|
+
exports.sum = sum;
|
|
1848
|
+
exports.sumBy = sumBy;
|
|
1849
|
+
exports.sumPower = sumPower;
|
|
1850
|
+
exports.symmetricDifference = symmetricDifference;
|
|
1851
|
+
exports.symmetricDifferenceBy = symmetricDifferenceBy;
|
|
1852
|
+
exports.symmetricDifferenceWith = symmetricDifferenceWith;
|
|
1853
|
+
exports.tail = tail;
|
|
1854
|
+
exports.take = take;
|
|
1855
|
+
exports.takeRight = takeRight;
|
|
1856
|
+
exports.takeRightWhile = takeRightWhile;
|
|
1857
|
+
exports.takeWhile = takeWhile;
|
|
1858
|
+
exports.throttle = throttle;
|
|
1859
|
+
exports.times = times;
|
|
1860
|
+
exports.timeTaken = timeTaken;
|
|
1861
|
+
exports.toCamelCase = toCamelCase;
|
|
1862
|
+
exports.toCurrency = toCurrency;
|
|
1863
|
+
exports.toDecimalMark = toDecimalMark;
|
|
1864
|
+
exports.toggleClass = toggleClass;
|
|
1865
|
+
exports.toHash = toHash;
|
|
1866
|
+
exports.toKebabCase = toKebabCase;
|
|
1867
|
+
exports.tomorrow = tomorrow;
|
|
1868
|
+
exports.toOrdinalSuffix = toOrdinalSuffix;
|
|
1869
|
+
exports.toSafeInteger = toSafeInteger;
|
|
1870
|
+
exports.toSnakeCase = toSnakeCase;
|
|
1871
|
+
exports.toTitleCase = toTitleCase;
|
|
1872
|
+
exports.transform = transform;
|
|
1873
|
+
exports.triggerEvent = triggerEvent;
|
|
1874
|
+
exports.truncateString = truncateString;
|
|
1875
|
+
exports.truthCheckCollection = truthCheckCollection;
|
|
1876
|
+
exports.unary = unary;
|
|
1877
|
+
exports.uncurry = uncurry;
|
|
1878
|
+
exports.unescapeHTML = unescapeHTML;
|
|
1879
|
+
exports.unflattenObject = unflattenObject;
|
|
1880
|
+
exports.unfold = unfold;
|
|
1881
|
+
exports.union = union;
|
|
1882
|
+
exports.unionBy = unionBy;
|
|
1883
|
+
exports.unionWith = unionWith;
|
|
1884
|
+
exports.uniqueElements = uniqueElements;
|
|
1885
|
+
exports.uniqueElementsBy = uniqueElementsBy;
|
|
1886
|
+
exports.uniqueElementsByRight = uniqueElementsByRight;
|
|
1887
|
+
exports.uniqueSymmetricDifference = uniqueSymmetricDifference;
|
|
1888
|
+
exports.untildify = untildify;
|
|
1889
|
+
exports.unzip = unzip;
|
|
1890
|
+
exports.unzipWith = unzipWith;
|
|
1891
|
+
exports.URLJoin = URLJoin;
|
|
1892
|
+
exports.UUIDGeneratorBrowser = UUIDGeneratorBrowser;
|
|
1893
|
+
exports.UUIDGeneratorNode = UUIDGeneratorNode;
|
|
1894
|
+
exports.validateNumber = validateNumber;
|
|
1895
|
+
exports.vectorDistance = vectorDistance;
|
|
1896
|
+
exports.when = when;
|
|
1897
|
+
exports.without = without;
|
|
1898
|
+
exports.words = words;
|
|
1899
|
+
exports.xProd = xProd;
|
|
1900
|
+
exports.yesNo = yesNo;
|
|
1901
|
+
exports.yesterday = yesterday;
|
|
1902
|
+
exports.zip = zip;
|
|
1903
|
+
exports.zipObject = zipObject;
|
|
1904
|
+
exports.zipWith = zipWith;
|
|
1905
|
+
exports.binarySearch = binarySearch;
|
|
1906
|
+
exports.celsiusToFahrenheit = celsiusToFahrenheit;
|
|
1907
|
+
exports.cleanObj = cleanObj;
|
|
1908
|
+
exports.collatz = collatz;
|
|
1909
|
+
exports.countVowels = countVowels;
|
|
1910
|
+
exports.factors = factors;
|
|
1911
|
+
exports.fahrenheitToCelsius = fahrenheitToCelsius;
|
|
1912
|
+
exports.fibonacciCountUntilNum = fibonacciCountUntilNum;
|
|
1913
|
+
exports.fibonacciUntilNum = fibonacciUntilNum;
|
|
1914
|
+
exports.heronArea = heronArea;
|
|
1915
|
+
exports.howManyTimes = howManyTimes;
|
|
1916
|
+
exports.httpDelete = httpDelete;
|
|
1917
|
+
exports.httpPut = httpPut;
|
|
1918
|
+
exports.isArmstrongNumber = isArmstrongNumber;
|
|
1919
|
+
exports.isSimilar = isSimilar;
|
|
1920
|
+
exports.JSONToDate = JSONToDate;
|
|
1921
|
+
exports.kmphToMph = kmphToMph;
|
|
1922
|
+
exports.levenshteinDistance = levenshteinDistance;
|
|
1923
|
+
exports.mphToKmph = mphToKmph;
|
|
1924
|
+
exports.pipeLog = pipeLog;
|
|
1925
|
+
exports.quickSort = quickSort;
|
|
1926
|
+
exports.removeVowels = removeVowels;
|
|
1927
|
+
exports.solveRPN = solveRPN;
|
|
1928
|
+
exports.speechSynthesis = speechSynthesis;
|
|
1929
|
+
exports.squareSum = squareSum;
|
|
1930
|
+
|
|
1931
|
+
export default exports
|