Yesterday, I gave an interview after a long time, and I was asked a question which I couldn't solve on the spot.
I had to implement a sort function for a Array of strings in JavaScript, with the following requirements:
- The Array will always contain Strings
- For sorting, Upper Case has higher priority than Lowe Case Letters, with Numbers having the Least.
- Assume that Array.sort() cannot be used
- The performance of the sorting is not a factor; i.e. Bubble sort is fine.
I was thinking of the solution today, and came up with this:
function sortArray(items) {
let itemcount = items.length;
for (var i = 0; i < itemcount; i++) { //number of passes
for (var j = 0; j < (itemcount - 1 - i); j++) { //for checking all pairs in a given pass
let a = items[j];
let b = items[j + 1];
if (compareCaseSenitiveStrings(a, b) < 0) {
console.log("Switch", a, b)
items[j + 1] = a;
items[j] = b;
}
}
}
//return
return items;
}
//Function to compare two given strings, and return the index of the higher priority one
function compareCaseSenitiveStrings(a, b) {
//Inner functions
function compareCharacters(a, b) {
//check the case first()
if (a.getFirstCase() == b.getFirstCase()) {
let charDiff = a.codePointAt(0) - b.codePointAt(0);
return -Math.sign(charDiff)
} else {
//different cases
//We need to pass the id of the one which is higher;
let requiredCaseOrder = ["NONE", "LOWER", "UPPER"];
return requiredCaseOrder.indexOf(a.getFirstCase()) - requiredCaseOrder.indexOf(b.getFirstCase());
}
}
function isNumeric(n) {
return !isNaN(parseFloat(n)) && isFinite(n);
}
//End of inner functions
//===============================================
//Start of function here
//First check if both are numbers
if (isNumeric(a) && isNumeric(b)) {
//return the index of smaller number (since it has higher priority)
return -Math.sign((parseFloat(a) - parseFloat(b)));
}
//Now check that lengths of both is greater than 0
if ((a.length > 0) && (b.length > 0)) {
//check the first elements of this string
let result = compareCharacters(a[0], b[0]);
if (result != 0) {
//this means one input has higher priority, lets return that
return result;
} else {
//both are equal
//get the result of remaining characters
return compareCaseSenitiveStrings(a.substring(1), b.substring(1));
}
} else {
//length of atleast one of these strings is zero.
//return the index of the longer element
let lengthDiff = a.length - b.length;
return Math.sign(lengthDiff);
}
}
String.prototype.getFirstCase = function() {
let caseEnum = ["LOWER", "NONE", "UPPER"];
var caseIndex = 1;
if (this == this.toLowerCase()) {
caseIndex--;
}
if (this == this.toUpperCase()) {
caseIndex++;
}
return caseEnum[caseIndex];
};
Is this code readable enough? Are there any other Design Patterns that could be applied? Any other points which could be improved?