I have the array of strings that I want to sort in a custom order My array looks like this
["E", "D", "CC", "C", "B", "BB", "BBA", "BBD", "BBE", "BBB", "BBBC", "A", "AA"]
In my sorted array I want to show the words alphabetically but the words with large number of continuous letter should appear first.
If more number of words have same length of continuous letter then need to consider next letter alphabetically.
My expected result should look like this
["AA", "A","BBBC", "BBB","BBA", "BBD", "BBE", "BB", "B", "CC", "C", "D", "E"]
I tried to sort using the default sort() function but it didn't give me expected results. So please give your suggestions
Juan Pablo Isaza
I'd first write a function that compares 2 elements with the expected rules and returns 1 if the first element should be first, else -1, check the length of the 2 elements and see if the longest starts with the smallest (like in "AAA"
and "A"
)
function myComparer(a, b)
{
if (a.length < b.length)
{
if (b.startsWith(a))
{
return 1; // a should be after b
}
}
else if (a.length > b.length)
{
if (a.startsWith(b))
{
return -1; // b should be after a
}
}
if (a < b)
{
return -1;
}
return 1;
}
const CompareTester = (a, b) => {
if (myComparer(a, b) == -1)
{
console.log(`"${a}" then "${b}"`);
}
else
{
console.log(`"${b}" then "${a}"`);
}
}
const testArr = [
{ a: "AAA", b: "A" },
{ a: "A", b: "AAA" },
{ a: "BBA", b: "BB" },
{ a: "A", b: "B" },
{ a: "ABC", b: "DEF" },
{ a: "ABC", b: "ABCDEF" }
];
for (elem of testArr)
{
CompareTester(elem.a, elem.b);
}
Now, you can use this function as a callback for the .sort()
method :
const arr = ["E", "D", "CC", "C", "B", "BB", "BBA", "BBD", "BBE", "BBB", "BBBC", "A", "AA"];
function myComparer(a, b)
{
if (a.length < b.length)
{
if (b.startsWith(a))
{
return 1; // a should be after b
}
}
else if (a.length > b.length)
{
if (a.startsWith(b))
{
return -1; // b should be after a
}
}
if (a < b)
{
return -1;
}
return 1;
}
arr.sort(myComparer);
console.log(arr);
You need your own custom sorting algorithm for this kind of sorting.
var yourArray = ["E", "D", "CC", "C", "B", "BB", "BBB", "A", "AA"]; // Unsorted Array
let customerSort = (arr) =>
{
// This loop is for iterating array
for (var i = 0; i < arr.length; i++)
{
// This loop is for comparing each item of the array with all items in array
for (var j = 0; j < arr.length; j++)
{
// This condition is for sorting array in alphabetical order
if (arr[i] < arr[j])
{
var x = arr[i];
arr[i] = arr[j];
arr[j] = x;
}
// This condition is for sorting array in the custom order needed
if (arr[i].charAt(0) == arr[j].charAt(0) && arr[i].length > arr[j].length)
{
var x = arr[i];
arr[i] = arr[j];
arr[j] = x;
}
}
}
// Return Sorted Array
return arr;
}
console.log(customerSort(yourArray));
The challenge was understanding the sort rules implicit in the question, but I think I can restate the OP to suggest that the strings should be sorted first by the lexical order of the first letter, then by the run length of the first set of repeating characters, then by the whole string length, and last by the lexical order of the remaining chars.
To expose that logic clearly in the sort, This snippet preprocesses the input strings into objects like:
{ input: "BBBC", firstChar: "B", runLength: 3, fallback: "C", length: 4 }
If all that's right, then the sort is simple...
function sortInfo(original) {
const firstLetter = original[0];
const length = original.length;
let runLength = 0;
for (let letter of original) {
if (letter === firstLetter) runLength++;
else break;
}
const fallback = original.slice(runLength)
return { original, firstLetter, runLength, length, fallback }
}
let input = ["E", "D", "CC", "C", "B", "BB", "BBA", "BBD", "BBE", "BBB", "BBBC", "A", "AA"];
let sortable = input.map(sortInfo)
sortable.sort((a,b) => {
if (a.firstLetter !== b.firstLetter) return a.firstLetter.localeCompare(b.firstLetter);
if (a.runLength !== b.runLength) return b.runLength - a.runLength;
if (a.length !== b.length) return b.length - a.length;
return a.fallback.localeCompare(b.fallback);
});
console.log(sortable.map(o => o.original))