5

I am trying to order this array in Javascript

arr = ["ax", "mof", "4", "63", "42", "3", "10", "[", "23", "adidas", "ba", ")", "ABC"]; 

And i want that the array is showed like this:

["3", "4", "10", "23", "42", "63", "ABC", "adidas", "ax", "ba", "mof", ")", "["]

Considering the symbols ")" , "[" too.

The order that i want to be the array is:

  1. the numbers from minor to mayor
  2. then the words, the capital letter doesn't matter.
  3. Finally, the symbols.

I know that i must use sort(), but the problem is i can't order the array with the symbols, i have that problem

I am using that code to show the array and the ordered array in HTML

var arr, text, larr, i; 
arr = ["ax", "mof", "4", "63", "42", "3", "10", "[", "23", "adidas", "ba", ")", "ABC"]; 
larr = arr.length;

text = "<ul>";
for (i = 0; i < larr; i++) {
  text += "<li>" + arr[i] + "</li>";
}
text += "</ul>";

document.getElementById("arrayin").innerHTML = text;

console.log(arr);

var arror,textor, larror, j;

arror = arr.sort();

larror = arror.length;

textor = "<ul>";
for (j = 0; j < larror; j++) {
  textor += "<li>" + arror[j] + "</li>";
}
textor += "</ul>";

console.log(arror);

document.getElementById("Oarray").innerHTML = textor;

My final question is how can i order the array with the numbers, letters and symbols

Calvin Nunes
  • 6,376
  • 4
  • 20
  • 48
J1293
  • 71
  • 1
  • 8
  • You'll need to create a custom sort function and pass it as `arr.sort(sortFunction);`. which takes 2 parameters. Inside the sort function, you'll need to first compare if both parameters are both numberlike, if they are, return the appropriate integer for their comparison (with number-like strings compared as numbers) and if they are not, then set both to uppercase and compare them lexicographically. โ€“ Sunny Patel Oct 11 '18 at 17:28

4 Answers4

4

As you guessed you do have to use the sort method and pass in a compare function. In order to get the order you are looking for the following checks will work. Full working example on jsfiddle here - https://jsfiddle.net/aczhyk8j/1/

function compare(a, b) {
  // check for numberhood
  const numA = !isNaN(a);
  const numB = !isNaN(b);

  if (numA && numB) {
    return Number(a) - Number(b);
  }

  if (numA) return -1;
  if (numB) return 1;

  // check for wordhood
  const wordA = /^[a-zA-Z]+$/.test(a);
  const wordB = /^[a-zA-Z]+$/.test(b);

  if (wordA && wordB) {
    return a.localeCompare(b);
  }

  if (wordA) return -1;
  if (wordB) return 1;

  return 1; // or whatever logic to sort within non-alphanumeric values
}

// Now, use it in your sort method call.
let arr = ["ax", "mof", "4", "63", "42", "3", "10", "[", "23", "adidas", "ba", ")", "ABC"];

arr.sort(compare);
console.log(arr);
kabirbaidhya
  • 3,264
  • 3
  • 34
  • 59
Tope
  • 938
  • 2
  • 11
  • 15
  • Chinese words are considered as special symbols, will you make change to considered as alphabets โ€“ kushal Apr 24 '19 at 06:47
  • Can you please tell me how to tweak the above code if I want the output in the below format; [ "3", "4", "10", "23", "42", "63", "A", "B", C", "M", "a", "b", "c", "m", Adidas", "ax", "ba", "mof", ")", "[" ] . I mean number first, then just A to Z letters, then words and symbols. Thanks in advance โ€“ Itsme Jun 19 '22 at 15:27
3

Using a custom sort() function you can achieve what you want.

It's not easy and may need some "hacky" way to separete 'symbols' from normal characters. I used this "hacky" way, but maybe someone can help with some regEx or other way.

My hack is to have an array of possible symbols and then inside the sort(), when one of the itens that is being compared is equal to one of the symbols, temporary change it to a string "zzzzzzz" this will probably make it go to the last position since the sort is from "a" to "z".

The sort() function needs to return 1, 0 or -1, so it is what the custom compare() function do. It first see if the comparing words are valid numbers, if yes, then compare to see which one comes first. Then if it is not numbers, compare it as strings in upperCase, since you said that case doesn't matter (using the normal lexographical sort)

Test the below code to see if it is what you need.

var arr = ["ax", "mof", "4", "63", "42", "3", "10", "[", "23", "adidas", "ba", ")", "ABC"]
var symbols = "()[]{}!@#$%ยจ&*-_=+".split("");

function compare(array){
  array.sort((a,b) => {
  
    if (symbols.indexOf(a) > -1) a = "zzzzzzz"    
    if (symbols.indexOf(b) > -1) b = "zzzzzzz"

    if (!isNaN(Number(a)) && !isNaN(Number(b))){      
        if (Number(a) > Number(b)){
          return 1;
        }else if(Number(a) < Number(b)){
          return -1;
        }else{
          return 0;
        }
        
    }else{         
      if (a.toUpperCase() > b.toUpperCase()){
          return 1;
      }else if(a.toUpperCase() < b.toUpperCase()){
        return -1;
      }else{
        return 0;
      }      
    }    
  })
  return array;
}

console.log(compare(arr))
Calvin Nunes
  • 6,376
  • 4
  • 20
  • 48
3

I used sort with this custom comparator function. Recall that the comparator should return a positive number if a should come before b, a negative number if b should come before a, and 0 if the elements are equal under the ordering.

let array = ["ax", "mof", "4", "63", "42", "3", "10", "[", "23", "adidas", "ba", ")", "ABC", "abc"];

array.sort((a, b) => {
  const aStr = String(a).toLowerCase();
  const bStr = String(b).toLowerCase();

  // Alphanumeric elements always come before non-alphanumeric elements
  const aIsAlphanumeric = isAlphanumeric(aStr);
  const bIsAlphanumeric = isAlphanumeric(bStr);
  if (aIsAlphanumeric && !bIsAlphanumeric) {
    return -1;
  } else if (bIsAlphanumeric && !aIsAlphanumeric) {
    return 1;
  }

  // Numerical elements always come before alphabetic elements
  const aNum = Number(a);
  const bNum = Number(b);
  // If both are numerical, sort in the usual fashion (smaller goes first)
  if (aNum && bNum) {
    return aNum - bNum;
    // If a is numerical but b isn't, put a first.
  } else if (aNum) {
    return -1;
    // If b is numerical but a isn't, put b first.
  } else if (bNum) {
    return 1;
  }

  // In all other cases, default to usual sort order.
  return aStr.localeCompare(bStr);
});

console.log(array);

function isAlphanumeric(str) {
  var code, i, len;

  for (i = 0, len = str.length; i < len; i++) {
    code = str.charCodeAt(i);
    if (!(code > 47 && code < 58) && // numeric (0-9)
      !(code > 64 && code < 91) && // upper alpha (A-Z)
      !(code > 96 && code < 123)) { // lower alpha (a-z)
      return false;
    }
  }

  return true;
}

Note: The isAlphanumeric function is taken from this answer.

kabirbaidhya
  • 3,264
  • 3
  • 34
  • 59
0

You can override the default sort by passing compare function.

function compare(a, b) {
  // Check if number, and if number, parse and compare.

  // Check other logics

}

arr.sort(compare);

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/sort#Parameters

Pavan Andhukuri
  • 1,547
  • 3
  • 23
  • 49