@fileverse-dev/formulajs 4.4.17 → 4.4.19

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/cjs/index.cjs CHANGED
@@ -1270,48 +1270,79 @@ 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, sort_order = 1, by_col = false) {
1274
- if (!array || !Array.isArray(array)) {
1275
- return na
1276
- }
1273
+ function SORT(inputArray, sortIndex = 1, isAscending, sortByColumn = false) {
1274
+ if (!inputArray || !Array.isArray(inputArray)) return na;
1275
+ if (inputArray.length === 0) return 0;
1277
1276
 
1278
- if (array.length === 0) {
1279
- return 0
1280
- }
1277
+ let sortColumnIndex = parseNumber(sortIndex);
1278
+ if (!sortColumnIndex || sortColumnIndex < 1) return value;
1279
+ sortColumnIndex = sortColumnIndex - 1;
1281
1280
 
1282
- sort_index = parseNumber(sort_index);
1283
- if (!sort_index || sort_index < 1) {
1284
- return value
1285
- }
1281
+ const sortDirection = isAscending.toLowerCase() === 'false' ? -1 : 1;
1282
+ const parsedSortDirection = parseNumber(sortDirection);
1283
+ if (parsedSortDirection !== 1 && parsedSortDirection !== -1) return value;
1286
1284
 
1287
- sort_order = parseNumber(sort_order);
1288
- if (sort_order !== 1 && sort_order !== -1) {
1289
- return value
1290
- }
1291
1285
 
1292
- by_col = parseBool(by_col);
1293
- if (typeof by_col !== 'boolean') {
1294
- return name
1286
+ const isSortByColumn = parseBool(sortByColumn);
1287
+ if (typeof isSortByColumn !== "boolean") return name;
1288
+
1289
+
1290
+ const normalizedMatrix = fillMatrix(inputArray);
1291
+ const orientedMatrix = isSortByColumn
1292
+ ? transpose(normalizedMatrix)
1293
+ : normalizedMatrix;
1294
+
1295
+ if (!orientedMatrix.length || !orientedMatrix[0] || sortColumnIndex >= orientedMatrix[0].length) {
1296
+ return value;
1295
1297
  }
1296
1298
 
1297
- const sortArray = (arr) =>
1298
- arr.sort((a, b) => {
1299
- a = parseString(a[sort_index - 1]);
1300
- b = parseString(b[sort_index - 1]);
1299
+ const isBlank = (value) => value === "" || value === null || value === undefined;
1301
1300
 
1302
- return sort_order === 1 ? (a < b ? sort_order * -1 : sort_order) : a > b ? sort_order : sort_order * -1
1303
- });
1301
+ // Comparator for sorting values
1302
+ const compareValues = (a, b) => {
1303
+ const aBlank = isBlank(a);
1304
+ const bBlank = isBlank(b);
1305
+ if (aBlank && bBlank) return 0;
1306
+ if (aBlank) return 1;
1307
+ if (bBlank) return -1;
1304
1308
 
1305
- const matrix = fillMatrix(array);
1306
- const result = by_col ? transpose(matrix) : matrix;
1309
+ // Numeric comparison if possible
1310
+ const parsedA = parseNumber(a);
1311
+ const parsedB = parseNumber(b);
1312
+ const isANumber = Number.isFinite(parsedA);
1313
+ const isBNumber = Number.isFinite(parsedB);
1314
+
1315
+ if (isANumber && isBNumber) {
1316
+ if (parsedA < parsedB) return -1;
1317
+ if (parsedA > parsedB) return 1;
1318
+ return 0;
1319
+ }
1320
+
1321
+ // Fallback: case-insensitive string comparison
1322
+ const stringA = (parseString(a) ?? "").toString().toLowerCase();
1323
+ const stringB = (parseString(b) ?? "").toString().toLowerCase();
1324
+ if (stringA < stringB) return -1;
1325
+ if (stringA > stringB) return 1;
1326
+ return 0;
1327
+ };
1307
1328
 
1308
- return sort_index >= 1 && sort_index <= result[0].length
1309
- ? by_col
1310
- ? transpose(sortArray(result))
1311
- : sortArray(result)
1312
- : value
1329
+ const rowsWithOriginalIndex = orientedMatrix.map((row, rowIndex) => ({ row, rowIndex }));
1330
+
1331
+ rowsWithOriginalIndex.sort((rowA, rowB) => {
1332
+ const baseComparison = compareValues(rowA.row[sortColumnIndex], rowB.row[sortColumnIndex]);
1333
+ if (baseComparison !== 0) return baseComparison * parsedSortDirection;
1334
+ return rowA.rowIndex - rowB.rowIndex;
1335
+ });
1336
+
1337
+ // Extract sorted rows
1338
+ const sortedMatrix = rowsWithOriginalIndex.map((item) => item.row);
1339
+
1340
+ // Return rows or columns depending on orientation
1341
+ return isSortByColumn ? transpose(sortedMatrix) : sortedMatrix;
1313
1342
  }
1314
1343
 
1344
+
1345
+
1315
1346
  /**
1316
1347
  * Returns the transpose of an array.
1317
1348
  *
package/lib/esm/index.mjs CHANGED
@@ -1268,48 +1268,79 @@ 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, sort_order = 1, by_col = false) {
1272
- if (!array || !Array.isArray(array)) {
1273
- return na
1274
- }
1271
+ function SORT(inputArray, sortIndex = 1, isAscending, sortByColumn = false) {
1272
+ if (!inputArray || !Array.isArray(inputArray)) return na;
1273
+ if (inputArray.length === 0) return 0;
1275
1274
 
1276
- if (array.length === 0) {
1277
- return 0
1278
- }
1275
+ let sortColumnIndex = parseNumber(sortIndex);
1276
+ if (!sortColumnIndex || sortColumnIndex < 1) return value;
1277
+ sortColumnIndex = sortColumnIndex - 1;
1279
1278
 
1280
- sort_index = parseNumber(sort_index);
1281
- if (!sort_index || sort_index < 1) {
1282
- return value
1283
- }
1279
+ const sortDirection = isAscending.toLowerCase() === 'false' ? -1 : 1;
1280
+ const parsedSortDirection = parseNumber(sortDirection);
1281
+ if (parsedSortDirection !== 1 && parsedSortDirection !== -1) return value;
1284
1282
 
1285
- sort_order = parseNumber(sort_order);
1286
- if (sort_order !== 1 && sort_order !== -1) {
1287
- return value
1288
- }
1289
1283
 
1290
- by_col = parseBool(by_col);
1291
- if (typeof by_col !== 'boolean') {
1292
- return name
1284
+ const isSortByColumn = parseBool(sortByColumn);
1285
+ if (typeof isSortByColumn !== "boolean") return name;
1286
+
1287
+
1288
+ const normalizedMatrix = fillMatrix(inputArray);
1289
+ const orientedMatrix = isSortByColumn
1290
+ ? transpose(normalizedMatrix)
1291
+ : normalizedMatrix;
1292
+
1293
+ if (!orientedMatrix.length || !orientedMatrix[0] || sortColumnIndex >= orientedMatrix[0].length) {
1294
+ return value;
1293
1295
  }
1294
1296
 
1295
- const sortArray = (arr) =>
1296
- arr.sort((a, b) => {
1297
- a = parseString(a[sort_index - 1]);
1298
- b = parseString(b[sort_index - 1]);
1297
+ const isBlank = (value) => value === "" || value === null || value === undefined;
1299
1298
 
1300
- return sort_order === 1 ? (a < b ? sort_order * -1 : sort_order) : a > b ? sort_order : sort_order * -1
1301
- });
1299
+ // Comparator for sorting values
1300
+ const compareValues = (a, b) => {
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;
1302
1306
 
1303
- const matrix = fillMatrix(array);
1304
- const result = by_col ? transpose(matrix) : matrix;
1307
+ // Numeric comparison if possible
1308
+ const parsedA = parseNumber(a);
1309
+ const parsedB = parseNumber(b);
1310
+ const isANumber = Number.isFinite(parsedA);
1311
+ const isBNumber = Number.isFinite(parsedB);
1312
+
1313
+ if (isANumber && isBNumber) {
1314
+ if (parsedA < parsedB) return -1;
1315
+ if (parsedA > parsedB) return 1;
1316
+ return 0;
1317
+ }
1318
+
1319
+ // Fallback: case-insensitive string comparison
1320
+ const stringA = (parseString(a) ?? "").toString().toLowerCase();
1321
+ const stringB = (parseString(b) ?? "").toString().toLowerCase();
1322
+ if (stringA < stringB) return -1;
1323
+ if (stringA > stringB) return 1;
1324
+ return 0;
1325
+ };
1305
1326
 
1306
- return sort_index >= 1 && sort_index <= result[0].length
1307
- ? by_col
1308
- ? transpose(sortArray(result))
1309
- : sortArray(result)
1310
- : value
1327
+ const rowsWithOriginalIndex = orientedMatrix.map((row, rowIndex) => ({ row, rowIndex }));
1328
+
1329
+ rowsWithOriginalIndex.sort((rowA, rowB) => {
1330
+ const baseComparison = compareValues(rowA.row[sortColumnIndex], rowB.row[sortColumnIndex]);
1331
+ if (baseComparison !== 0) return baseComparison * parsedSortDirection;
1332
+ return rowA.rowIndex - rowB.rowIndex;
1333
+ });
1334
+
1335
+ // Extract sorted rows
1336
+ const sortedMatrix = rowsWithOriginalIndex.map((item) => item.row);
1337
+
1338
+ // Return rows or columns depending on orientation
1339
+ return isSortByColumn ? transpose(sortedMatrix) : sortedMatrix;
1311
1340
  }
1312
1341
 
1342
+
1343
+
1313
1344
  /**
1314
1345
  * Returns the transpose of an array.
1315
1346
  *
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@fileverse-dev/formulajs",
3
- "version": "4.4.17",
3
+ "version": "4.4.19",
4
4
  "description": "JavaScript implementation of most Microsoft Excel formula functions",
5
5
  "author": "Formulajs",
6
6
  "publishConfig": {
@@ -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?: any, sort_order?: any, by_col?: any): any;
3809
+ export function SORT(inputArray: any, sortIndex: number, isAscending: any, sortByColumn?: boolean): any;
3810
3810
  /**
3811
3811
  * Returns a positive square root.
3812
3812
  *
@@ -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?: any, sort_order?: any, by_col?: any): any;
3809
+ export function SORT(inputArray: any, sortIndex: number, isAscending: any, sortByColumn?: boolean): any;
3810
3810
  /**
3811
3811
  * Returns a positive square root.
3812
3812
  *