0

Say I have an array like this:

input = [
    "1.1",
    "1.c",
    "1.b",
    "1",
    "D",
    "b",
    "4",
    "2.1.2",
    "5.1",
    "3",
    "2.a.1"
]

What would be the best way to sort this and get result like this:

sorted = [
    "1",
    "1.1",
    "1.b",
    "1.c",
    "b",
    "2.a.1",
    "2.1.2",
    "3",
    "4",
    "D",
    "5.1"
]

Here, to sort, consider:

'a' or 'A' is equivalent to 1,

'b' or 'B' is equivalent to 2,

and so on.

The array contains numbers and letters only, no symbols.

So far I have tried:

input = ["1", "1.1", "1.b", "1.c", "b", "2.a.1", "2.1.2", "3", "4", "D", "5.1"]
console.log(input.sort((a, b) => a.localeCompare(b)));

Does not give me the desired result. Need help on it. Any suggestions, please?

1
  • You can use the sort() method to sort an array in JavaScript, but it sorts elements in lexicographic order by default. Commented Jan 19, 2023 at 6:59

2 Answers 2

3

You can do it using a function to transform the inputs and the sort function. Here is how I did it:

input = [
    "1.1",
    "1.c",
    "1.b",
    "1",
    "D",
    "b",
    "4",
    "2.1.2",
    "5.1",
    "3",
    "2.a.1"
]

function convert(el){
 const nums = el.split(".");
 return nums.map(n => {
    if(n.match(/[A-z]/)){ 
      return n.toLowerCase().charCodeAt(0) - 96;
    }
    return n;
  }).join(".");
}

input.sort((a,b) => {
  const convA = convert(a);
  const convB = convert(b);
  return convA.localeCompare(convB);
})

console.log(input);

Sign up to request clarification or add additional context in comments.

3 Comments

Your code is great but we could also do the following for the convert function convert(el){ const lowerCased = el.toLowerCase(); let key = ""; for (const c of lowerCased) { key += (c.charCodeAt(0) >= 97 && c.charCodeAt(0) <= 122) ? c.charCodeAt(0) - 96 : c; return key; }
Yes It can be simplified but I was trying to make it super simple to understand. But yes your solution is more compact.
I think yours is clearer, great solution!
2

Here is a simplified version of @mgm793's sort function:

input = [
    "1.1",
    "1.c",
    "1.b",
    "1",
    "D",
    "b",
    "4",
    "2.1.2",
    "5.1",
    "3",
    "2.a.1"
]

function conv(str){
 return str.toLowerCase().replace(/[a-z]/g,m=>m.charCodeAt(0)-96)
}

input.sort((a,b) =>conv(a).localeCompare(conv(b)))

console.log(input);

And here is another version that will also be stable for higher numbers (up to 26) and letters (up to z):

input = [
    "1.10",
    "1.m",
    "1.b",
    "1.1.3",
    "1",
    "F",
    "b",
    "4",
    "2.1.2",
    "5.1",
    "3",
    "2.a.1"
]

let res=input.map(e=>[e.toLowerCase().replace(/\d+/g,m=>String.fromCharCode(+m+96)),e])
             .sort(([a],[b])=>a.localeCompare(b))
             .map(([_,e])=>e);

console.log(res);

This snippet converts every number and every combination of digits and letters to a string consisting only of characters (a to z) and dots (.). These strings can easily be sorted using String.localeCompare(). They are combined with the original values into a temporary array. This array is then sorted and the original values are taken from it again in a final .map() loop. As a side effect of this approach the original array (input) remains unchanged while res becomes the sorted version of it.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.