I implemented below logic to apply sorting on mixed data(contains alphanumeric and numeric values) but it is not sorting as expected.
/*For numeric value sorting */
if (!isNaN(fVal) && !isNaN(lastVal)) {
switch (policy) {
case SORT_BY_DESC:
return fVal < lastVal ? 1 : -1;
case SORT_BY_ASC:
return fVal > lastVal ? 1 : -1;
default:
return 0;
}
}
/* For alphanumeric sorting */
else {
switch (policy) {
case SORT_BY_DESC:
return fVal < lastVal ? 1 : -1;
case SORT_BY_ASC:
return fVal > lastVal ? 1 : -1;
default:
return 0;
}
}
If all the values are numeric this logic is working fine but if I have mixed data it is not sorting properly.
Raw Data - ['60091A0222', '633', '63372A1019', '63372A1021', '6667', '6789', '7776']
Expected Result -
Data in Descending order - 63372A1021, 63372A1019, 60091A0222, 7776, 6789, 633
Data in Ascending order - 633,, 6667, 6789, 7776, 60091A0222, 63372A1019, 63372A1021
What I am getting -
Descending order - 7776, 6789, 6667, 63372A1021, 63372A1019, 633, 60091A0222
Ascending order - 60091A0222, 633, 63372A1019, 63372A1021, 6667, 6789, 7776
CodePudding user response:
You could take a check for finiteness and sort this value to top.
const
data = ['60091A0222', 633, '63372A1019', '63372A1021', 6667, 6789, 7776],
asc = (a, b) => isFinite(b) - isFinite(a) || (a > b) - (a < b),
desc = (a, b) => isFinite(a) - isFinite(b) || (a < b) - (a > b)
data.sort(asc);
console.log(...data);
data.sort(desc);
console.log(...data);
CodePudding user response:
You will need to split the strings into number/letter/number groups and sort based on the presence of each type of group.
const sortIndices = (data, desc = false) => {
const pattern = /(?<=\d)(?=\D)|(?=\d)(?<=\D)/, dir = desc ? -1 : 1;
return data.sort((a, b) => {
const x = a.split(pattern), y = b.split(pattern);
let diff;
// Compare overall length
if (a.length < b.length) return -1 * dir;
if (b.length < a.length) return 1 * dir;
// Find the difference between the first group (numeric)
diff = x[0] - y[0];
if (diff !== 0) return diff * dir;
// If both contain at least two groups
if (a.length < 2) return -1 * dir;
if (b.length < 2) return 1 * dir;
// Find the difference between the second group (alpha)
diff = x[1].localeCompare(y[1]);
if (diff !== 0) return diff * dir;
// If both contain at least three groups
if (a.length < 3) return -1 * dir;
if (b.length < 3) return 1 * dir;
// Find the difference between the third group (numeric)
return ( x[2] - y[2]) * dir;
});
};
const data = ['7776', '6789', '6667', '63372A1021', '63372A1019', '633', '60091A0222'];
console.log(...sortIndices(data)); // Ascending
console.log(...sortIndices(data, true)); // Descending
.as-console-wrapper { top: 0; max-height: 100% !important; }