@fileverse-dev/formulajs 4.4.17 → 4.4.18
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/browser/formula.js +54 -27
- package/lib/browser/formula.min.js +2 -2
- package/lib/browser/formula.min.js.map +1 -1
- package/lib/cjs/index.cjs +58 -31
- package/lib/esm/index.mjs +58 -31
- package/package.json +1 -1
- package/types/cjs/index.d.cts +1 -1
- package/types/esm/index.d.mts +1 -1
package/lib/cjs/index.cjs
CHANGED
|
@@ -1270,48 +1270,75 @@ function ROWS(array) {
|
|
|
1270
1270
|
* @param {*} by_col Optional. A logical value indicating the desired sort direction; FALSE to sort by row (default), TRUE to sort by column
|
|
1271
1271
|
* @returns
|
|
1272
1272
|
*/
|
|
1273
|
-
function SORT(array, sort_index = 1,
|
|
1274
|
-
if (!array || !Array.isArray(array))
|
|
1275
|
-
|
|
1276
|
-
}
|
|
1273
|
+
function SORT(array, sort_index = 1, is_ascending, by_col = false) {
|
|
1274
|
+
if (!array || !Array.isArray(array)) return na;
|
|
1275
|
+
if (array.length === 0) return 0;
|
|
1277
1276
|
|
|
1278
|
-
|
|
1279
|
-
|
|
1280
|
-
|
|
1277
|
+
let idx = parseNumber(sort_index);
|
|
1278
|
+
if (!idx || idx < 1) return value;
|
|
1279
|
+
idx = idx - 1;
|
|
1281
1280
|
|
|
1282
|
-
|
|
1283
|
-
|
|
1284
|
-
|
|
1285
|
-
}
|
|
1281
|
+
const sortOrderNumber = is_ascending === 'FALSE' ? -1 : 1;
|
|
1282
|
+
let order = parseNumber(sortOrderNumber);
|
|
1283
|
+
if (order !== 1 && order !== -1) return value;
|
|
1286
1284
|
|
|
1287
|
-
|
|
1288
|
-
if (
|
|
1289
|
-
|
|
1290
|
-
|
|
1285
|
+
const byCol = parseBool(by_col);
|
|
1286
|
+
if (typeof byCol !== "boolean") return name;
|
|
1287
|
+
|
|
1288
|
+
// Rectangularize then orient
|
|
1289
|
+
const matrix = fillMatrix(array);
|
|
1290
|
+
const working = byCol ? transpose(matrix) : matrix;
|
|
1291
1291
|
|
|
1292
|
-
|
|
1293
|
-
|
|
1294
|
-
return name
|
|
1292
|
+
if (!working.length || !working[0] || idx >= working[0].length) {
|
|
1293
|
+
return value; // out of bounds
|
|
1295
1294
|
}
|
|
1296
1295
|
|
|
1297
|
-
|
|
1298
|
-
|
|
1299
|
-
a = parseString(a[sort_index - 1]);
|
|
1300
|
-
b = parseString(b[sort_index - 1]);
|
|
1296
|
+
// Helpers (aiming for spreadsheet-ish behavior)
|
|
1297
|
+
const isBlank = (v) => v === "" || v === null || v === undefined;
|
|
1301
1298
|
|
|
1302
|
-
|
|
1303
|
-
|
|
1299
|
+
const cmp = (a, b) => {
|
|
1300
|
+
// Blanks last (ascending); we'll multiply by order later for descending.
|
|
1301
|
+
const aBlank = isBlank(a);
|
|
1302
|
+
const bBlank = isBlank(b);
|
|
1303
|
+
if (aBlank && bBlank) return 0;
|
|
1304
|
+
if (aBlank) return 1;
|
|
1305
|
+
if (bBlank) return -1;
|
|
1304
1306
|
|
|
1305
|
-
|
|
1306
|
-
|
|
1307
|
+
// If both parse as finite numbers, compare numerically
|
|
1308
|
+
const na = parseNumber(a);
|
|
1309
|
+
const nb = parseNumber(b);
|
|
1310
|
+
const aNum = Number.isFinite(na);
|
|
1311
|
+
const bNum = Number.isFinite(nb);
|
|
1312
|
+
|
|
1313
|
+
if (aNum && bNum) {
|
|
1314
|
+
if (na < nb) return -1;
|
|
1315
|
+
if (na > nb) return 1;
|
|
1316
|
+
return 0;
|
|
1317
|
+
}
|
|
1318
|
+
|
|
1319
|
+
// Fallback: case-insensitive string compare
|
|
1320
|
+
const sa = (parseString(a) ?? "").toString().toLowerCase();
|
|
1321
|
+
const sb = (parseString(b) ?? "").toString().toLowerCase();
|
|
1322
|
+
if (sa < sb) return -1;
|
|
1323
|
+
if (sa > sb) return 1;
|
|
1324
|
+
return 0;
|
|
1325
|
+
};
|
|
1326
|
+
|
|
1327
|
+
// Stable sort: decorate with original index
|
|
1328
|
+
const decorated = working.map((row, i) => ({ row, i }));
|
|
1307
1329
|
|
|
1308
|
-
|
|
1309
|
-
|
|
1310
|
-
|
|
1311
|
-
|
|
1312
|
-
|
|
1330
|
+
decorated.sort((A, B) => {
|
|
1331
|
+
const base = cmp(A.row[idx], B.row[idx]);
|
|
1332
|
+
if (base !== 0) return base * order;
|
|
1333
|
+
// stable tiebreaker: original order
|
|
1334
|
+
return A.i - B.i;
|
|
1335
|
+
});
|
|
1336
|
+
|
|
1337
|
+
const sorted = decorated.map((d) => d.row);
|
|
1338
|
+
return byCol ? transpose(sorted) : sorted;
|
|
1313
1339
|
}
|
|
1314
1340
|
|
|
1341
|
+
|
|
1315
1342
|
/**
|
|
1316
1343
|
* Returns the transpose of an array.
|
|
1317
1344
|
*
|
package/lib/esm/index.mjs
CHANGED
|
@@ -1268,48 +1268,75 @@ function ROWS(array) {
|
|
|
1268
1268
|
* @param {*} by_col Optional. A logical value indicating the desired sort direction; FALSE to sort by row (default), TRUE to sort by column
|
|
1269
1269
|
* @returns
|
|
1270
1270
|
*/
|
|
1271
|
-
function SORT(array, sort_index = 1,
|
|
1272
|
-
if (!array || !Array.isArray(array))
|
|
1273
|
-
|
|
1274
|
-
}
|
|
1271
|
+
function SORT(array, sort_index = 1, is_ascending, by_col = false) {
|
|
1272
|
+
if (!array || !Array.isArray(array)) return na;
|
|
1273
|
+
if (array.length === 0) return 0;
|
|
1275
1274
|
|
|
1276
|
-
|
|
1277
|
-
|
|
1278
|
-
|
|
1275
|
+
let idx = parseNumber(sort_index);
|
|
1276
|
+
if (!idx || idx < 1) return value;
|
|
1277
|
+
idx = idx - 1;
|
|
1279
1278
|
|
|
1280
|
-
|
|
1281
|
-
|
|
1282
|
-
|
|
1283
|
-
}
|
|
1279
|
+
const sortOrderNumber = is_ascending === 'FALSE' ? -1 : 1;
|
|
1280
|
+
let order = parseNumber(sortOrderNumber);
|
|
1281
|
+
if (order !== 1 && order !== -1) return value;
|
|
1284
1282
|
|
|
1285
|
-
|
|
1286
|
-
if (
|
|
1287
|
-
|
|
1288
|
-
|
|
1283
|
+
const byCol = parseBool(by_col);
|
|
1284
|
+
if (typeof byCol !== "boolean") return name;
|
|
1285
|
+
|
|
1286
|
+
// Rectangularize then orient
|
|
1287
|
+
const matrix = fillMatrix(array);
|
|
1288
|
+
const working = byCol ? transpose(matrix) : matrix;
|
|
1289
1289
|
|
|
1290
|
-
|
|
1291
|
-
|
|
1292
|
-
return name
|
|
1290
|
+
if (!working.length || !working[0] || idx >= working[0].length) {
|
|
1291
|
+
return value; // out of bounds
|
|
1293
1292
|
}
|
|
1294
1293
|
|
|
1295
|
-
|
|
1296
|
-
|
|
1297
|
-
a = parseString(a[sort_index - 1]);
|
|
1298
|
-
b = parseString(b[sort_index - 1]);
|
|
1294
|
+
// Helpers (aiming for spreadsheet-ish behavior)
|
|
1295
|
+
const isBlank = (v) => v === "" || v === null || v === undefined;
|
|
1299
1296
|
|
|
1300
|
-
|
|
1301
|
-
|
|
1297
|
+
const cmp = (a, b) => {
|
|
1298
|
+
// Blanks last (ascending); we'll multiply by order later for descending.
|
|
1299
|
+
const aBlank = isBlank(a);
|
|
1300
|
+
const bBlank = isBlank(b);
|
|
1301
|
+
if (aBlank && bBlank) return 0;
|
|
1302
|
+
if (aBlank) return 1;
|
|
1303
|
+
if (bBlank) return -1;
|
|
1302
1304
|
|
|
1303
|
-
|
|
1304
|
-
|
|
1305
|
+
// If both parse as finite numbers, compare numerically
|
|
1306
|
+
const na = parseNumber(a);
|
|
1307
|
+
const nb = parseNumber(b);
|
|
1308
|
+
const aNum = Number.isFinite(na);
|
|
1309
|
+
const bNum = Number.isFinite(nb);
|
|
1310
|
+
|
|
1311
|
+
if (aNum && bNum) {
|
|
1312
|
+
if (na < nb) return -1;
|
|
1313
|
+
if (na > nb) return 1;
|
|
1314
|
+
return 0;
|
|
1315
|
+
}
|
|
1316
|
+
|
|
1317
|
+
// Fallback: case-insensitive string compare
|
|
1318
|
+
const sa = (parseString(a) ?? "").toString().toLowerCase();
|
|
1319
|
+
const sb = (parseString(b) ?? "").toString().toLowerCase();
|
|
1320
|
+
if (sa < sb) return -1;
|
|
1321
|
+
if (sa > sb) return 1;
|
|
1322
|
+
return 0;
|
|
1323
|
+
};
|
|
1324
|
+
|
|
1325
|
+
// Stable sort: decorate with original index
|
|
1326
|
+
const decorated = working.map((row, i) => ({ row, i }));
|
|
1305
1327
|
|
|
1306
|
-
|
|
1307
|
-
|
|
1308
|
-
|
|
1309
|
-
|
|
1310
|
-
|
|
1328
|
+
decorated.sort((A, B) => {
|
|
1329
|
+
const base = cmp(A.row[idx], B.row[idx]);
|
|
1330
|
+
if (base !== 0) return base * order;
|
|
1331
|
+
// stable tiebreaker: original order
|
|
1332
|
+
return A.i - B.i;
|
|
1333
|
+
});
|
|
1334
|
+
|
|
1335
|
+
const sorted = decorated.map((d) => d.row);
|
|
1336
|
+
return byCol ? transpose(sorted) : sorted;
|
|
1311
1337
|
}
|
|
1312
1338
|
|
|
1339
|
+
|
|
1313
1340
|
/**
|
|
1314
1341
|
* Returns the transpose of an array.
|
|
1315
1342
|
*
|
package/package.json
CHANGED
package/types/cjs/index.d.cts
CHANGED
|
@@ -3806,7 +3806,7 @@ export function SMARTCONTRACT(...args: any[]): Promise<any>;
|
|
|
3806
3806
|
* @param {*} by_col Optional. A logical value indicating the desired sort direction; FALSE to sort by row (default), TRUE to sort by column
|
|
3807
3807
|
* @returns
|
|
3808
3808
|
*/
|
|
3809
|
-
export function SORT(array: any, sort_index
|
|
3809
|
+
export function SORT(array: any, sort_index: any, is_ascending: any, by_col?: any): any;
|
|
3810
3810
|
/**
|
|
3811
3811
|
* Returns a positive square root.
|
|
3812
3812
|
*
|
package/types/esm/index.d.mts
CHANGED
|
@@ -3806,7 +3806,7 @@ export function SMARTCONTRACT(...args: any[]): Promise<any>;
|
|
|
3806
3806
|
* @param {*} by_col Optional. A logical value indicating the desired sort direction; FALSE to sort by row (default), TRUE to sort by column
|
|
3807
3807
|
* @returns
|
|
3808
3808
|
*/
|
|
3809
|
-
export function SORT(array: any, sort_index
|
|
3809
|
+
export function SORT(array: any, sort_index: any, is_ascending: any, by_col?: any): any;
|
|
3810
3810
|
/**
|
|
3811
3811
|
* Returns a positive square root.
|
|
3812
3812
|
*
|