df-script 1.5.0 → 1.6.0
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/README.md +124 -8
- package/dist/api.d.ts +1 -1
- package/dist/columnExpressions/ColumnExpr.d.ts +2 -2
- package/dist/columnExpressions/functions/coalesce.d.ts +2 -2
- package/dist/columnExpressions/functions/element.d.ts +1 -1
- package/dist/columnExpressions/functions/when.d.ts +2 -2
- package/dist/columnExpressions/index.d.ts +1 -1
- package/dist/columnExpressions/mixins/AggregationExpr.d.ts +2 -2
- package/dist/columnExpressions/mixins/ArithmeticExpr.d.ts +11 -10
- package/dist/columnExpressions/mixins/ArrayExpr.d.ts +39 -0
- package/dist/columnExpressions/mixins/ListExpr.d.ts +2 -2
- package/dist/columnExpressions/mixins/StringExpr.d.ts +2 -2
- package/dist/columnExpressions/types.d.ts +1 -0
- package/dist/constants.d.ts +11 -0
- package/dist/dataframe/dataframe.d.ts +1 -1
- package/dist/datatypes/index.d.ts +3 -2
- package/dist/datatypes/types.d.ts +7 -7
- package/dist/index.js +6 -6
- package/dist/types.d.ts +4 -2
- package/dist/utils/array.d.ts +217 -0
- package/dist/utils/binary.d.ts +3 -0
- package/dist/utils/date.d.ts +21 -35
- package/dist/utils/guards.d.ts +11 -10
- package/dist/utils/index.d.ts +3 -2
- package/dist/utils/list.d.ts +23 -1
- package/dist/utils/number.d.ts +14 -29
- package/dist/utils/object.d.ts +26 -0
- package/dist/utils/string.d.ts +3 -5
- package/package.json +2 -2
- package/dist/api.js +0 -26
- package/dist/bundle.min.js +0 -1
- package/dist/columnExpressions/ColumnExpr.js +0 -219
- package/dist/columnExpressions/ExprBase.js +0 -92
- package/dist/columnExpressions/constants.js +0 -7
- package/dist/columnExpressions/functions/all.js +0 -11
- package/dist/columnExpressions/functions/coalesce.js +0 -44
- package/dist/columnExpressions/functions/element.js +0 -11
- package/dist/columnExpressions/functions/exclude.js +0 -13
- package/dist/columnExpressions/functions/implode.js +0 -7
- package/dist/columnExpressions/functions/lit.js +0 -17
- package/dist/columnExpressions/functions/repeat.d.ts +0 -47
- package/dist/columnExpressions/functions/repeat.js +0 -131
- package/dist/columnExpressions/functions/seq_range.js +0 -91
- package/dist/columnExpressions/functions/when.js +0 -85
- package/dist/columnExpressions/index.js +0 -38
- package/dist/columnExpressions/mixins/AggregationExpr.js +0 -76
- package/dist/columnExpressions/mixins/ArithmeticExpr.js +0 -131
- package/dist/columnExpressions/mixins/BooleanExpr.d.ts +0 -40
- package/dist/columnExpressions/mixins/BooleanExpr.js +0 -67
- package/dist/columnExpressions/mixins/ComparisonExpr.js +0 -250
- package/dist/columnExpressions/mixins/ListExpr.js +0 -224
- package/dist/columnExpressions/mixins/LogicalExpr.js +0 -53
- package/dist/columnExpressions/mixins/ManipulationExpr.js +0 -71
- package/dist/columnExpressions/mixins/NumericExpr.d.ts +0 -92
- package/dist/columnExpressions/mixins/NumericExpr.js +0 -259
- package/dist/columnExpressions/mixins/StringExpr.js +0 -237
- package/dist/columnExpressions/mixins/StructExpr.js +0 -139
- package/dist/columnExpressions/mixins/TemporalExpr.js +0 -126
- package/dist/columnExpressions/mixins/WindowExpr.js +0 -151
- package/dist/columnExpressions/types.js +0 -2
- package/dist/columnExpressions/utils.js +0 -45
- package/dist/dataframe/constants.js +0 -7
- package/dist/dataframe/dataframe.js +0 -990
- package/dist/dataframe/grouped/grouped.js +0 -114
- package/dist/dataframe/index.js +0 -20
- package/dist/dataframe/types.js +0 -2
- package/dist/dataframe/utils.js +0 -307
- package/dist/datatypes/DataType.js +0 -76
- package/dist/datatypes/index.js +0 -46
- package/dist/datatypes/types/Binary.d.ts +0 -9
- package/dist/datatypes/types/Binary.js +0 -18
- package/dist/datatypes/types/Boolean.d.ts +0 -9
- package/dist/datatypes/types/Boolean.js +0 -19
- package/dist/datatypes/types/Date.d.ts +0 -8
- package/dist/datatypes/types/Date.js +0 -21
- package/dist/datatypes/types/Datetime.d.ts +0 -8
- package/dist/datatypes/types/Datetime.js +0 -17
- package/dist/datatypes/types/Decimal.d.ts +0 -10
- package/dist/datatypes/types/Decimal.js +0 -28
- package/dist/datatypes/types/Duration.d.ts +0 -8
- package/dist/datatypes/types/Duration.js +0 -17
- package/dist/datatypes/types/Float32.d.ts +0 -8
- package/dist/datatypes/types/Float32.js +0 -17
- package/dist/datatypes/types/Float64.d.ts +0 -8
- package/dist/datatypes/types/Float64.js +0 -17
- package/dist/datatypes/types/Int16.d.ts +0 -8
- package/dist/datatypes/types/Int16.js +0 -17
- package/dist/datatypes/types/Int32.d.ts +0 -8
- package/dist/datatypes/types/Int32.js +0 -17
- package/dist/datatypes/types/Int64.d.ts +0 -8
- package/dist/datatypes/types/Int64.js +0 -17
- package/dist/datatypes/types/Int8.d.ts +0 -8
- package/dist/datatypes/types/Int8.js +0 -17
- package/dist/datatypes/types/List.d.ts +0 -10
- package/dist/datatypes/types/List.js +0 -31
- package/dist/datatypes/types/Null.d.ts +0 -9
- package/dist/datatypes/types/Null.js +0 -17
- package/dist/datatypes/types/Object.d.ts +0 -9
- package/dist/datatypes/types/Object.js +0 -17
- package/dist/datatypes/types/Struct.d.ts +0 -14
- package/dist/datatypes/types/Struct.js +0 -39
- package/dist/datatypes/types/Time.d.ts +0 -8
- package/dist/datatypes/types/Time.js +0 -29
- package/dist/datatypes/types/UInt16.d.ts +0 -8
- package/dist/datatypes/types/UInt16.js +0 -17
- package/dist/datatypes/types/UInt32.d.ts +0 -8
- package/dist/datatypes/types/UInt32.js +0 -17
- package/dist/datatypes/types/UInt64.d.ts +0 -8
- package/dist/datatypes/types/UInt64.js +0 -17
- package/dist/datatypes/types/UInt8.d.ts +0 -8
- package/dist/datatypes/types/UInt8.js +0 -17
- package/dist/datatypes/types/Utf8.d.ts +0 -10
- package/dist/datatypes/types/Utf8.js +0 -20
- package/dist/datatypes/types.js +0 -290
- package/dist/exceptions/index.js +0 -46
- package/dist/exceptions/utils.js +0 -28
- package/dist/functions/concat.js +0 -260
- package/dist/functions/index.js +0 -9
- package/dist/functions/read_csv.js +0 -53
- package/dist/functions/read_json.js +0 -21
- package/dist/functions/transpose.d.ts +0 -7
- package/dist/functions/transpose.js +0 -84
- package/dist/types.js +0 -2
- package/dist/utils/boolean.d.ts +0 -1
- package/dist/utils/boolean.js +0 -18
- package/dist/utils/csv.js +0 -313
- package/dist/utils/date.js +0 -348
- package/dist/utils/guards.js +0 -112
- package/dist/utils/index.js +0 -23
- package/dist/utils/json.js +0 -217
- package/dist/utils/list.js +0 -361
- package/dist/utils/number.js +0 -401
- package/dist/utils/string.js +0 -209
package/dist/utils/number.js
DELETED
|
@@ -1,401 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.BIGINT_RANGES = exports.INT_RANGES = void 0;
|
|
4
|
-
exports.isValidNumber = isValidNumber;
|
|
5
|
-
exports.toValidNumber = toValidNumber;
|
|
6
|
-
exports.formatNumber = formatNumber;
|
|
7
|
-
exports.isValidFloat = isValidFloat;
|
|
8
|
-
exports.toValidFloat = toValidFloat;
|
|
9
|
-
exports.isValidInt = isValidInt;
|
|
10
|
-
exports.toValidInt = toValidInt;
|
|
11
|
-
exports.isValidBigInt = isValidBigInt;
|
|
12
|
-
exports.toValidBigInt = toValidBigInt;
|
|
13
|
-
exports.isValidDecimal = isValidDecimal;
|
|
14
|
-
exports.toValidDecimal = toValidDecimal;
|
|
15
|
-
exports.clamp = clamp;
|
|
16
|
-
exports.mulberry32 = mulberry32;
|
|
17
|
-
exports.computeMedian = computeMedian;
|
|
18
|
-
exports.computeQuantile = computeQuantile;
|
|
19
|
-
exports.computeMode = computeMode;
|
|
20
|
-
const guards_1 = require("./guards");
|
|
21
|
-
const list_1 = require("./list");
|
|
22
|
-
const NUMERIC_CLEAN_REGEX = /[,\s_]/g;
|
|
23
|
-
const VALID_DECIMAL_REGEX = /^[+-]?\d+(?:\.\d+)?$/;
|
|
24
|
-
function isValidNumber(v, options) {
|
|
25
|
-
if (typeof v !== "number")
|
|
26
|
-
return false;
|
|
27
|
-
if (options && options.allowNonFiniteNumbers)
|
|
28
|
-
return true;
|
|
29
|
-
return !Number.isNaN(v) && Number.isFinite(v);
|
|
30
|
-
}
|
|
31
|
-
function toValidNumber(v, options) {
|
|
32
|
-
if (v == null)
|
|
33
|
-
return null;
|
|
34
|
-
if (typeof v === "symbol")
|
|
35
|
-
return null;
|
|
36
|
-
if (isValidNumber(v, options)) {
|
|
37
|
-
return v;
|
|
38
|
-
}
|
|
39
|
-
if (typeof v === "boolean") {
|
|
40
|
-
return v ? 1 : 0;
|
|
41
|
-
}
|
|
42
|
-
if (typeof v === "bigint") {
|
|
43
|
-
const n = Number(v);
|
|
44
|
-
return isValidNumber(n, options) ? n : null;
|
|
45
|
-
}
|
|
46
|
-
if (v instanceof Date) {
|
|
47
|
-
const t = v.getTime();
|
|
48
|
-
return isValidNumber(t, options) ? t : null;
|
|
49
|
-
}
|
|
50
|
-
if (typeof v === "string") {
|
|
51
|
-
const clean = v.trim().replace(NUMERIC_CLEAN_REGEX, "");
|
|
52
|
-
if (clean === "")
|
|
53
|
-
return null;
|
|
54
|
-
const n = Number(clean);
|
|
55
|
-
if (Number.isNaN(n)) {
|
|
56
|
-
if (options?.allowNonFiniteNumbers && clean.toLowerCase() === "nan") {
|
|
57
|
-
return NaN;
|
|
58
|
-
}
|
|
59
|
-
return null;
|
|
60
|
-
}
|
|
61
|
-
return isValidNumber(n, options) ? n : null;
|
|
62
|
-
}
|
|
63
|
-
return null;
|
|
64
|
-
}
|
|
65
|
-
/**
|
|
66
|
-
* Formats any numeric value (number, bigint, numeric string, Date, etc.) for output,
|
|
67
|
-
* handling NaN, Infinity, scientific notation, precision, and accounting formats.
|
|
68
|
-
*/
|
|
69
|
-
function formatNumber({ locale = "en-US", accountingNegatives = false, fallback = "NaN", ...intlOpts } = {}) {
|
|
70
|
-
if (intlOpts.useGrouping === undefined) {
|
|
71
|
-
intlOpts.useGrouping = false;
|
|
72
|
-
}
|
|
73
|
-
if (intlOpts.maximumFractionDigits === undefined && intlOpts.maximumSignificantDigits === undefined) {
|
|
74
|
-
intlOpts.maximumFractionDigits = 20;
|
|
75
|
-
}
|
|
76
|
-
const formatter = new Intl.NumberFormat(locale, intlOpts);
|
|
77
|
-
return (value) => {
|
|
78
|
-
if (typeof value === "bigint") {
|
|
79
|
-
if (accountingNegatives && value < 0n) {
|
|
80
|
-
return `(${formatter.format(-value)})`;
|
|
81
|
-
}
|
|
82
|
-
return formatter.format(value);
|
|
83
|
-
}
|
|
84
|
-
const num = toValidNumber(value, { allowNonFiniteNumbers: true });
|
|
85
|
-
if (num === null || Number.isNaN(num)) {
|
|
86
|
-
return fallback;
|
|
87
|
-
}
|
|
88
|
-
if (!Number.isFinite(num)) {
|
|
89
|
-
if (accountingNegatives && num === -Infinity) {
|
|
90
|
-
return "(Infinity)";
|
|
91
|
-
}
|
|
92
|
-
return String(num);
|
|
93
|
-
}
|
|
94
|
-
if (accountingNegatives && num < 0) {
|
|
95
|
-
return `(${formatter.format(Math.abs(num))})`;
|
|
96
|
-
}
|
|
97
|
-
return formatter.format(num);
|
|
98
|
-
};
|
|
99
|
-
}
|
|
100
|
-
function isValidFloat(v, { floatPrecision, allowNonFiniteNumbers = false, floatScientific = false } = {}) {
|
|
101
|
-
let num;
|
|
102
|
-
if (typeof v === "number") {
|
|
103
|
-
num = v;
|
|
104
|
-
}
|
|
105
|
-
else if (floatScientific && typeof v === "string") {
|
|
106
|
-
const parsed = parseFloat(v);
|
|
107
|
-
if (Number.isNaN(parsed))
|
|
108
|
-
return false;
|
|
109
|
-
num = parsed;
|
|
110
|
-
}
|
|
111
|
-
else {
|
|
112
|
-
return false;
|
|
113
|
-
}
|
|
114
|
-
if (floatPrecision === "Float32") {
|
|
115
|
-
num = Math.fround(num);
|
|
116
|
-
}
|
|
117
|
-
if (!allowNonFiniteNumbers && (Number.isNaN(num) || !Number.isFinite(num))) {
|
|
118
|
-
return false;
|
|
119
|
-
}
|
|
120
|
-
return true;
|
|
121
|
-
}
|
|
122
|
-
function toValidFloat(v, { floatPrecision = "Float64", allowNonFiniteNumbers = true, floatScientific = false } = {}) {
|
|
123
|
-
let num = toValidNumber(v, { allowNonFiniteNumbers });
|
|
124
|
-
if (num === null && floatScientific && typeof v === "string") {
|
|
125
|
-
const parsed = parseFloat(v);
|
|
126
|
-
if (isValidNumber(parsed, { allowNonFiniteNumbers })) {
|
|
127
|
-
num = parsed;
|
|
128
|
-
}
|
|
129
|
-
}
|
|
130
|
-
if (num === null)
|
|
131
|
-
return null;
|
|
132
|
-
if (floatPrecision === "Float32") {
|
|
133
|
-
num = Math.fround(num);
|
|
134
|
-
}
|
|
135
|
-
if (!allowNonFiniteNumbers && !Number.isFinite(num)) {
|
|
136
|
-
return null;
|
|
137
|
-
}
|
|
138
|
-
return num;
|
|
139
|
-
}
|
|
140
|
-
// ============================================================================
|
|
141
|
-
// /** Integer Functions */
|
|
142
|
-
// ============================================================================
|
|
143
|
-
exports.INT_RANGES = {
|
|
144
|
-
Int8: { min: -128, max: 127 },
|
|
145
|
-
Int16: { min: -32768, max: 32767 },
|
|
146
|
-
Int32: { min: -2147483648, max: 2147483647 },
|
|
147
|
-
UInt8: { min: 0, max: 255 },
|
|
148
|
-
UInt16: { min: 0, max: 65535 },
|
|
149
|
-
UInt32: { min: 0, max: 4294967295 }
|
|
150
|
-
};
|
|
151
|
-
function isValidInt(v, range) {
|
|
152
|
-
if (!isValidNumber(v))
|
|
153
|
-
return false;
|
|
154
|
-
if (!Number.isInteger(v))
|
|
155
|
-
return false;
|
|
156
|
-
if (!range)
|
|
157
|
-
return true;
|
|
158
|
-
const limits = typeof range === "string" ? exports.INT_RANGES[range] : range;
|
|
159
|
-
return v >= limits.min && v <= limits.max;
|
|
160
|
-
}
|
|
161
|
-
function toValidInt(v, { range = "Int32", coerce = "truncate" } = {}) {
|
|
162
|
-
const num = toValidNumber(v);
|
|
163
|
-
if (num === null)
|
|
164
|
-
return null;
|
|
165
|
-
let n = num;
|
|
166
|
-
switch (coerce) {
|
|
167
|
-
case "round":
|
|
168
|
-
n = Math.round(n);
|
|
169
|
-
break;
|
|
170
|
-
case "floor":
|
|
171
|
-
n = Math.floor(n);
|
|
172
|
-
break;
|
|
173
|
-
case "ceil":
|
|
174
|
-
n = Math.ceil(n);
|
|
175
|
-
break;
|
|
176
|
-
case "truncate":
|
|
177
|
-
n = Math.trunc(n);
|
|
178
|
-
break;
|
|
179
|
-
}
|
|
180
|
-
const limits = typeof range === "string" ? exports.INT_RANGES[range] : range;
|
|
181
|
-
return clamp(n, { min: limits.min, max: limits.max });
|
|
182
|
-
}
|
|
183
|
-
// ============================================================================
|
|
184
|
-
// /** BigInt Functions */
|
|
185
|
-
// ============================================================================
|
|
186
|
-
exports.BIGINT_RANGES = {
|
|
187
|
-
Int64: { min: -9223372036854775808n, max: 9223372036854775807n },
|
|
188
|
-
UInt64: { min: 0n, max: 18446744073709551615n }
|
|
189
|
-
};
|
|
190
|
-
function isValidBigInt(v, range) {
|
|
191
|
-
if (typeof v !== "bigint")
|
|
192
|
-
return false;
|
|
193
|
-
if (!range)
|
|
194
|
-
return true;
|
|
195
|
-
const limits = typeof range === "string" ? exports.BIGINT_RANGES[range] : range;
|
|
196
|
-
return v >= limits.min && v <= limits.max;
|
|
197
|
-
}
|
|
198
|
-
function toValidBigInt(v, { range = "Int64", truncate = false } = {}) {
|
|
199
|
-
if (v == null)
|
|
200
|
-
return null;
|
|
201
|
-
if (typeof v === "symbol")
|
|
202
|
-
return null;
|
|
203
|
-
let bigintVal = null;
|
|
204
|
-
if (typeof v === "bigint") {
|
|
205
|
-
bigintVal = v;
|
|
206
|
-
}
|
|
207
|
-
else if (typeof v === "boolean") {
|
|
208
|
-
bigintVal = v ? 1n : 0n;
|
|
209
|
-
}
|
|
210
|
-
else if (typeof v === "string") {
|
|
211
|
-
const clean = v.trim().replace(NUMERIC_CLEAN_REGEX, "");
|
|
212
|
-
if (clean === "")
|
|
213
|
-
return null;
|
|
214
|
-
if (!VALID_DECIMAL_REGEX.test(clean)) {
|
|
215
|
-
const num = toValidNumber(clean);
|
|
216
|
-
if (num === null)
|
|
217
|
-
return null;
|
|
218
|
-
if (!truncate && !Number.isInteger(num))
|
|
219
|
-
return null;
|
|
220
|
-
bigintVal = BigInt(Math.trunc(num));
|
|
221
|
-
}
|
|
222
|
-
else {
|
|
223
|
-
if (!truncate && clean.includes("."))
|
|
224
|
-
return null;
|
|
225
|
-
const dotIdx = clean.indexOf(".");
|
|
226
|
-
bigintVal = BigInt(dotIdx !== -1 ? clean.slice(0, dotIdx) : clean);
|
|
227
|
-
}
|
|
228
|
-
}
|
|
229
|
-
else {
|
|
230
|
-
const num = toValidNumber(v);
|
|
231
|
-
if (num === null)
|
|
232
|
-
return null;
|
|
233
|
-
if (!truncate && !Number.isInteger(num))
|
|
234
|
-
return null;
|
|
235
|
-
bigintVal = BigInt(Math.trunc(num));
|
|
236
|
-
}
|
|
237
|
-
const limits = typeof range === "string" ? exports.BIGINT_RANGES[range] : range;
|
|
238
|
-
return clamp(bigintVal, { min: limits.min, max: limits.max });
|
|
239
|
-
}
|
|
240
|
-
function getDecimalMaxVal(precision, scale) {
|
|
241
|
-
const integerDigits = precision - scale;
|
|
242
|
-
const maxVal = Math.pow(10, integerDigits) - Math.pow(10, -scale);
|
|
243
|
-
return maxVal > 0 ? maxVal : null;
|
|
244
|
-
}
|
|
245
|
-
function roundToScale(v, scale) {
|
|
246
|
-
const str = v.toString();
|
|
247
|
-
if (str.includes("e")) {
|
|
248
|
-
const factor = Math.pow(10, scale);
|
|
249
|
-
return Math.round(v * factor) / factor;
|
|
250
|
-
}
|
|
251
|
-
return Number(Math.round(Number(str + "e" + scale)) + "e-" + scale);
|
|
252
|
-
}
|
|
253
|
-
function isValidDecimal(v, { precision, scale = 0 } = {}) {
|
|
254
|
-
if (!isValidNumber(v))
|
|
255
|
-
return false;
|
|
256
|
-
if (precision !== undefined) {
|
|
257
|
-
const maxVal = getDecimalMaxVal(precision, scale);
|
|
258
|
-
if (maxVal !== null && Math.abs(v) > maxVal) {
|
|
259
|
-
return false;
|
|
260
|
-
}
|
|
261
|
-
}
|
|
262
|
-
if (scale !== undefined) {
|
|
263
|
-
const rounded = roundToScale(v, scale);
|
|
264
|
-
if (Math.abs(v - rounded) > 1e-12) {
|
|
265
|
-
return false;
|
|
266
|
-
}
|
|
267
|
-
}
|
|
268
|
-
return true;
|
|
269
|
-
}
|
|
270
|
-
function toValidDecimal(v, { precision, scale } = {}) {
|
|
271
|
-
const num = toValidNumber(v);
|
|
272
|
-
if (num === null)
|
|
273
|
-
return null;
|
|
274
|
-
let n = num;
|
|
275
|
-
if (scale !== undefined) {
|
|
276
|
-
n = roundToScale(n, scale);
|
|
277
|
-
}
|
|
278
|
-
if (precision !== undefined) {
|
|
279
|
-
const scaleVal = scale ?? 0;
|
|
280
|
-
const maxVal = getDecimalMaxVal(precision, scaleVal);
|
|
281
|
-
if (maxVal !== null) {
|
|
282
|
-
n = clamp(n, { min: -maxVal, max: maxVal });
|
|
283
|
-
}
|
|
284
|
-
}
|
|
285
|
-
return n;
|
|
286
|
-
}
|
|
287
|
-
// ============================================================================
|
|
288
|
-
// /** Math & Stats Functions */
|
|
289
|
-
// ============================================================================
|
|
290
|
-
function clamp(val, { min = null, max = null, safe = true } = {}) {
|
|
291
|
-
if (min !== null && max !== null && min > max) {
|
|
292
|
-
return min;
|
|
293
|
-
}
|
|
294
|
-
let v = val;
|
|
295
|
-
if (safe && typeof v === "number") {
|
|
296
|
-
if (Number.isNaN(v)) {
|
|
297
|
-
// NaN can't be compared — coerce to the nearest boundary, preferring min
|
|
298
|
-
v = min !== null ? min : (max !== null ? max : val);
|
|
299
|
-
}
|
|
300
|
-
else if (v === Infinity) {
|
|
301
|
-
v = max !== null ? max : val;
|
|
302
|
-
}
|
|
303
|
-
else if (v === -Infinity) {
|
|
304
|
-
v = min !== null ? min : val;
|
|
305
|
-
}
|
|
306
|
-
}
|
|
307
|
-
if (min !== null && v < min)
|
|
308
|
-
return min;
|
|
309
|
-
if (max !== null && v > max)
|
|
310
|
-
return max;
|
|
311
|
-
return v;
|
|
312
|
-
}
|
|
313
|
-
/**
|
|
314
|
-
* Creates a seedable pseudo-random number generator using the Mulberry32 PRNG algorithm.
|
|
315
|
-
* Returns a function that generates a pseudo-random float in the range [0, 1).
|
|
316
|
-
*/
|
|
317
|
-
function mulberry32(seed) {
|
|
318
|
-
let s = seed | 0;
|
|
319
|
-
return function () {
|
|
320
|
-
let t = s = (s + 0x6D2B79F5) | 0;
|
|
321
|
-
t = Math.imul(t ^ (t >>> 15), t | 1);
|
|
322
|
-
t ^= t + Math.imul(t ^ (t >>> 7), t | 61);
|
|
323
|
-
return ((t ^ (t >>> 14)) >>> 0) / 4294967296;
|
|
324
|
-
};
|
|
325
|
-
}
|
|
326
|
-
function getSortedValidNumbers(values) {
|
|
327
|
-
const len = values.length;
|
|
328
|
-
let validCount = 0;
|
|
329
|
-
const nums = new Float64Array(len);
|
|
330
|
-
for (let i = 0; i < len; i++) {
|
|
331
|
-
const val = values[i];
|
|
332
|
-
// Only include actual numbers that aren't NaN (but preserve Infinity for bounds)
|
|
333
|
-
if (typeof val === "number" && !Number.isNaN(val)) {
|
|
334
|
-
nums[validCount++] = val;
|
|
335
|
-
}
|
|
336
|
-
}
|
|
337
|
-
if (validCount === 0)
|
|
338
|
-
return null;
|
|
339
|
-
const validNums = nums.subarray(0, validCount);
|
|
340
|
-
validNums.sort();
|
|
341
|
-
return validNums;
|
|
342
|
-
}
|
|
343
|
-
/**
|
|
344
|
-
* Computes the median of a numeric array, filtering out non-numeric and NaN values.
|
|
345
|
-
* Returns null if no valid numbers remain.
|
|
346
|
-
*/
|
|
347
|
-
function computeMedian(values) {
|
|
348
|
-
const validNums = getSortedValidNumbers(values);
|
|
349
|
-
if (!validNums)
|
|
350
|
-
return null;
|
|
351
|
-
const len = validNums.length;
|
|
352
|
-
const mid = Math.floor(len / 2);
|
|
353
|
-
return len % 2 !== 0 ? validNums[mid] : (validNums[mid - 1] + validNums[mid]) / 2;
|
|
354
|
-
}
|
|
355
|
-
/**
|
|
356
|
-
* Computes the quantile of a numeric array using linear interpolation, filtering out non-numeric and NaN values.
|
|
357
|
-
* q must be in [0, 1]. Returns null if no valid numbers remain or q is out of bounds.
|
|
358
|
-
*/
|
|
359
|
-
function computeQuantile(values, q) {
|
|
360
|
-
if (q < 0 || q > 1)
|
|
361
|
-
return null;
|
|
362
|
-
const validNums = getSortedValidNumbers(values);
|
|
363
|
-
if (!validNums)
|
|
364
|
-
return null;
|
|
365
|
-
const len = validNums.length;
|
|
366
|
-
const idx = q * (len - 1);
|
|
367
|
-
const low = Math.floor(idx);
|
|
368
|
-
const high = Math.ceil(idx);
|
|
369
|
-
if (low === high)
|
|
370
|
-
return validNums[low];
|
|
371
|
-
return validNums[low] + (idx - low) * (validNums[high] - validNums[low]);
|
|
372
|
-
}
|
|
373
|
-
/**
|
|
374
|
-
* Computes the mode(s) of an array, filtering out null/undefined values.
|
|
375
|
-
* Returns an array of the most frequent values, sorted, or null if empty/no mode.
|
|
376
|
-
*/
|
|
377
|
-
function computeMode(values) {
|
|
378
|
-
if (!(0, guards_1.isArrayOrTypedArray)(values) || values.length === 0)
|
|
379
|
-
return null;
|
|
380
|
-
const counts = new Map();
|
|
381
|
-
const len = values.length;
|
|
382
|
-
let max = 0;
|
|
383
|
-
let modes = [];
|
|
384
|
-
for (let i = 0; i < len; i++) {
|
|
385
|
-
const val = values[i];
|
|
386
|
-
if (val == null)
|
|
387
|
-
continue;
|
|
388
|
-
const c = (counts.get(val) ?? 0) + 1;
|
|
389
|
-
counts.set(val, c);
|
|
390
|
-
if (c > max) {
|
|
391
|
-
max = c;
|
|
392
|
-
modes = [val];
|
|
393
|
-
}
|
|
394
|
-
else if (c === max) {
|
|
395
|
-
modes.push(val);
|
|
396
|
-
}
|
|
397
|
-
}
|
|
398
|
-
if (modes.length === 0)
|
|
399
|
-
return null;
|
|
400
|
-
return (0, list_1.sortList)(modes);
|
|
401
|
-
}
|
package/dist/utils/string.js
DELETED
|
@@ -1,209 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.stripChars = stripChars;
|
|
4
|
-
exports.isBlankString = isBlankString;
|
|
5
|
-
exports.toCanonicalString = toCanonicalString;
|
|
6
|
-
const guards_1 = require("./guards");
|
|
7
|
-
const date_1 = require("./date");
|
|
8
|
-
/**
|
|
9
|
-
* Strips characters from the start, end, or both ends of a string.
|
|
10
|
-
*/
|
|
11
|
-
function stripChars(str, characters = null, { mode = "both", returnStringOnNull = false, maxScanStart = 1, maxScanEnd = 1, maxMatchesStart = 1, maxMatchesEnd = 1, trimFirst = false, stringOptions: { literal = false, caseInsensitive = false } = {} } = {}) {
|
|
12
|
-
if (str == null) {
|
|
13
|
-
return returnStringOnNull ? "" : null;
|
|
14
|
-
}
|
|
15
|
-
const trimString = (s, m = "both") => {
|
|
16
|
-
if (m === "start")
|
|
17
|
-
return s.trimStart();
|
|
18
|
-
if (m === "end")
|
|
19
|
-
return s.trimEnd();
|
|
20
|
-
return s.trim();
|
|
21
|
-
};
|
|
22
|
-
let workStr = str;
|
|
23
|
-
if (trimFirst && characters != null) {
|
|
24
|
-
workStr = trimString(str, mode);
|
|
25
|
-
}
|
|
26
|
-
if (characters == null) {
|
|
27
|
-
const result = trimString(workStr, mode);
|
|
28
|
-
return (returnStringOnNull || result !== "") ? result : null;
|
|
29
|
-
}
|
|
30
|
-
const matches = characters instanceof RegExp
|
|
31
|
-
? (char) => characters.test(char)
|
|
32
|
-
: (() => {
|
|
33
|
-
const targetSet = new Set(caseInsensitive ? characters.toLowerCase() : characters);
|
|
34
|
-
return (char) => targetSet.has(caseInsensitive ? char.toLowerCase() : char);
|
|
35
|
-
})();
|
|
36
|
-
const len = workStr.length;
|
|
37
|
-
const stripped = new Uint8Array(len);
|
|
38
|
-
const scanNonLiteral = ({ isStart, limit, maxMatches }) => {
|
|
39
|
-
if (len === 0 || maxMatches === 0) {
|
|
40
|
-
return;
|
|
41
|
-
}
|
|
42
|
-
const start = isStart ? 0 : len - 1;
|
|
43
|
-
const end = isStart ? len : -1;
|
|
44
|
-
const step = isStart ? 1 : -1;
|
|
45
|
-
let inBlock = false;
|
|
46
|
-
let matchesFound = 0;
|
|
47
|
-
let totalSkipped = 0;
|
|
48
|
-
for (let i = start; i !== end; i += step) {
|
|
49
|
-
if (matches(workStr[i])) {
|
|
50
|
-
if (!inBlock) {
|
|
51
|
-
if (limit !== null && limit >= 0 && totalSkipped >= limit) {
|
|
52
|
-
break;
|
|
53
|
-
}
|
|
54
|
-
if (maxMatches !== null && maxMatches >= 0 && matchesFound >= maxMatches) {
|
|
55
|
-
break;
|
|
56
|
-
}
|
|
57
|
-
inBlock = true;
|
|
58
|
-
matchesFound++;
|
|
59
|
-
}
|
|
60
|
-
stripped[i] = 1;
|
|
61
|
-
}
|
|
62
|
-
else {
|
|
63
|
-
inBlock = false;
|
|
64
|
-
totalSkipped++;
|
|
65
|
-
}
|
|
66
|
-
}
|
|
67
|
-
};
|
|
68
|
-
const scanLiteral = ({ isStart, limit, maxMatches }) => {
|
|
69
|
-
if (len === 0 || maxMatches === 0) {
|
|
70
|
-
return;
|
|
71
|
-
}
|
|
72
|
-
const patLen = characters.length;
|
|
73
|
-
if (patLen === 0) {
|
|
74
|
-
return;
|
|
75
|
-
}
|
|
76
|
-
const searchStr = caseInsensitive ? workStr.toLowerCase() : workStr;
|
|
77
|
-
const patStr = caseInsensitive ? characters.toLowerCase() : characters;
|
|
78
|
-
let currentIdx = isStart ? 0 : len - 1;
|
|
79
|
-
let matchesFound = 0;
|
|
80
|
-
let totalSkipped = 0;
|
|
81
|
-
while (currentIdx >= 0 && currentIdx < len) {
|
|
82
|
-
if (maxMatches !== null && maxMatches >= 0 && matchesFound >= maxMatches) {
|
|
83
|
-
break;
|
|
84
|
-
}
|
|
85
|
-
const searchStart = isStart ? currentIdx : (currentIdx - patLen + 1);
|
|
86
|
-
if (!isStart && searchStart < 0) {
|
|
87
|
-
break;
|
|
88
|
-
}
|
|
89
|
-
const matchIdx = isStart
|
|
90
|
-
? searchStr.indexOf(patStr, searchStart)
|
|
91
|
-
: searchStr.lastIndexOf(patStr, searchStart);
|
|
92
|
-
if (matchIdx === -1) {
|
|
93
|
-
break;
|
|
94
|
-
}
|
|
95
|
-
const skippedInThisStep = isStart
|
|
96
|
-
? (matchIdx - currentIdx)
|
|
97
|
-
: (currentIdx - (matchIdx + patLen - 1));
|
|
98
|
-
totalSkipped += skippedInThisStep;
|
|
99
|
-
if (limit !== null && limit >= 0 && totalSkipped >= limit) {
|
|
100
|
-
break;
|
|
101
|
-
}
|
|
102
|
-
for (let i = 0; i < patLen; i++) {
|
|
103
|
-
stripped[matchIdx + i] = 1;
|
|
104
|
-
}
|
|
105
|
-
matchesFound++;
|
|
106
|
-
currentIdx = isStart ? (matchIdx + patLen) : (matchIdx - 1);
|
|
107
|
-
}
|
|
108
|
-
};
|
|
109
|
-
const isLiteral = literal && typeof characters === "string";
|
|
110
|
-
const scan = isLiteral ? scanLiteral : scanNonLiteral;
|
|
111
|
-
if (mode === "both" || mode === "start") {
|
|
112
|
-
scan({ isStart: true, limit: maxScanStart, maxMatches: maxMatchesStart });
|
|
113
|
-
}
|
|
114
|
-
if (mode === "both" || mode === "end") {
|
|
115
|
-
scan({ isStart: false, limit: maxScanEnd, maxMatches: maxMatchesEnd });
|
|
116
|
-
}
|
|
117
|
-
let result = "";
|
|
118
|
-
for (let i = 0; i < len; i++) {
|
|
119
|
-
if (stripped[i] === 0) {
|
|
120
|
-
result += workStr[i];
|
|
121
|
-
}
|
|
122
|
-
}
|
|
123
|
-
return (returnStringOnNull || result !== "") ? result : null;
|
|
124
|
-
}
|
|
125
|
-
function isBlankString(v) {
|
|
126
|
-
if (typeof v === "string") {
|
|
127
|
-
return v.trim().length === 0;
|
|
128
|
-
}
|
|
129
|
-
if (v instanceof String) {
|
|
130
|
-
return v.valueOf().trim().length === 0;
|
|
131
|
-
}
|
|
132
|
-
return false;
|
|
133
|
-
}
|
|
134
|
-
function toCanonicalString(val, { depth = 0, maxDepth = 50 } = {}) {
|
|
135
|
-
if (depth > maxDepth) {
|
|
136
|
-
return "v:circular";
|
|
137
|
-
}
|
|
138
|
-
if (val === null) {
|
|
139
|
-
return "v:null";
|
|
140
|
-
}
|
|
141
|
-
if (val === undefined) {
|
|
142
|
-
return "v:undefined";
|
|
143
|
-
}
|
|
144
|
-
if (val instanceof Date) {
|
|
145
|
-
return (0, date_1.isValidDateObj)(val) ? `d:${val.getTime()}` : "d:invalid";
|
|
146
|
-
}
|
|
147
|
-
if ((0, guards_1.isTypedArray)(val)) {
|
|
148
|
-
return `u:${val.constructor.name}:${val.toString()}`;
|
|
149
|
-
}
|
|
150
|
-
if (Array.isArray(val)) {
|
|
151
|
-
const len = val.length;
|
|
152
|
-
const parts = new Array(len);
|
|
153
|
-
const nextOpt = { depth: depth + 1, maxDepth };
|
|
154
|
-
for (let i = 0; i < len; i++) {
|
|
155
|
-
parts[i] = toCanonicalString(val[i], nextOpt);
|
|
156
|
-
}
|
|
157
|
-
return `a:[${parts.join(",")}]`;
|
|
158
|
-
}
|
|
159
|
-
if (val instanceof Set) {
|
|
160
|
-
const arr = Array.from(val);
|
|
161
|
-
const len = arr.length;
|
|
162
|
-
const parts = new Array(len);
|
|
163
|
-
const nextOpt = { depth: depth + 1, maxDepth };
|
|
164
|
-
for (let i = 0; i < len; i++) {
|
|
165
|
-
parts[i] = toCanonicalString(arr[i], nextOpt);
|
|
166
|
-
}
|
|
167
|
-
parts.sort();
|
|
168
|
-
return `set:[${parts.join(",")}]`;
|
|
169
|
-
}
|
|
170
|
-
if (val instanceof Map) {
|
|
171
|
-
const keys = Array.from(val.keys());
|
|
172
|
-
const len = keys.length;
|
|
173
|
-
const parts = new Array(len);
|
|
174
|
-
const nextOpt = { depth: depth + 1, maxDepth };
|
|
175
|
-
for (let i = 0; i < len; i++) {
|
|
176
|
-
const k = keys[i];
|
|
177
|
-
parts[i] = `${toCanonicalString(k, nextOpt)}:${toCanonicalString(val.get(k), nextOpt)}`;
|
|
178
|
-
}
|
|
179
|
-
parts.sort();
|
|
180
|
-
return `map:{${parts.join(",")}}`;
|
|
181
|
-
}
|
|
182
|
-
if (typeof val === "object" && typeof val.toJSON === "function") {
|
|
183
|
-
return `j:${toCanonicalString(val.toJSON(), { depth: depth + 1, maxDepth })}`;
|
|
184
|
-
}
|
|
185
|
-
if ((0, guards_1.isPlainObj)(val)) {
|
|
186
|
-
const keys = Object.keys(val).sort();
|
|
187
|
-
const len = keys.length;
|
|
188
|
-
const parts = new Array(len);
|
|
189
|
-
const nextOpt = { depth: depth + 1, maxDepth };
|
|
190
|
-
for (let i = 0; i < len; i++) {
|
|
191
|
-
const k = keys[i];
|
|
192
|
-
parts[i] = `${k}:${toCanonicalString(val[k], nextOpt)}`;
|
|
193
|
-
}
|
|
194
|
-
return `o:{${parts.join(",")}}`;
|
|
195
|
-
}
|
|
196
|
-
if (val instanceof RegExp) {
|
|
197
|
-
return `r:${val.toString()}`;
|
|
198
|
-
}
|
|
199
|
-
if (typeof val === "function") {
|
|
200
|
-
return `f:${val.toString()}`;
|
|
201
|
-
}
|
|
202
|
-
if (typeof val === "string") {
|
|
203
|
-
return `s:${val}`;
|
|
204
|
-
}
|
|
205
|
-
if (typeof val === "symbol") {
|
|
206
|
-
return `y:${val.toString()}`;
|
|
207
|
-
}
|
|
208
|
-
return `${typeof val}:${val}`;
|
|
209
|
-
}
|