Cosmin Ciolacu
Cosmin Ciolacu

Reputation: 494

order roman-numbers in javascript

I have a function in javascript where the schoolClass it's an roman number like this I, II, IV etc. this function is called multiple times and the result it's concatenated in an array like this:

const generateClasses = (schoolClass, number) => {
  const classes = [];

  for (let i = 0; i < number; i++) {
    classes.push(`${schoolClass}-${(i + 10).toString(36).toUpperCase()}`);
  }
  return classes;
};
let output = [];
output = output.concat(generateClasses('II', 2));
output = output.concat(generateClasses('I', 1));
output = output.concat(generateClasses('IV', 2));
console.log(output);

in the end the output it's like this:

["II-A", "II-B", "I-A", "IV-A", "IV-B"]

how to order the array-like ["I-A", "II-A", "II-B", "IV-A", "IV-V"] I appreciate any help! PS: for converting numbers in roman I use the roman-numbers module

Upvotes: 0

Views: 737

Answers (3)

trincot
trincot

Reputation: 350345

As school grades are limited to 12, the alphabetical sort isn't that bad to start with. For the example you have given you could just call .sort() on that array and it would be fine.

Actually, only "IX" would get sorted at the wrong place. So let's deal with that:

let classes = ["XII-A", "IX-A", "VII-A", "II-A", "II-B", "I-A", "IV-A", "IV-B"];
let trans = s => s.replace("IX", "VIIJ");
classes.sort((a, b) => trans(a).localeCompare(trans(b)));
console.log(classes);

This would work for Roman numbers that don't use any other symbols than I, V and X, so up to 39.

Upvotes: 2

sourav satyam
sourav satyam

Reputation: 986

Here I converted the Roman to Integer by iterating each Roman character So XII will be (10+1+1)

Now Sort them but if 2 Roman character are same than I compare the Alphabet attached with it.

const num = ["II-B", "II-A", "I-A", "IV-A", "IV-B"];

num.sort((a, b) => {
  const diff = roman_to_Int(a.split("-")[0]) - roman_to_Int(b.split('-')[0]);
  if (diff === 0) {
    return a.split("-")[1].localeCompare(b.split("-")[1]);
  }
  return diff;

});

console.log(num);

/* Source - https://www.w3resource.com/javascript-exercises/javascript-math-exercise-22.php */

function roman_to_Int(str1) {
  if(str1 == null) return -1;
  var num = char_to_int(str1.charAt(0));
  var pre, curr;
  for(var i = 1; i < str1.length; i++){
    curr = char_to_int(str1.charAt(i));
    pre = char_to_int(str1.charAt(i-1));
    if(curr <= pre){
      num += curr;
    } else {
      num = num - pre*2 + curr;
    }
  }
  return num;
}

function char_to_int(c){
    switch (c){
      case 'I': return 1;
      case 'V': return 5;
      case 'X': return 10;
      case 'L': return 50;
      case 'C': return 100;
      case 'D': return 500;
      case 'M': return 1000;
      default: return -1;
    }
}

Upvotes: 0

VLAZ
VLAZ

Reputation: 29032

You need to convert the Roman numeral to a normal (Arabic) one to compare. Since you have very constrained amount of Roman numerals, the easiest way is to just hardcode them - no need to involve an algorithm that transforms them if you only have 12 different possible inputs.

With hardcoded values for I to XII, you can sort based on multiple criteria by splitting your string on - and:

const romanTable = {
  "I"   : 1,
  "II"  : 2,
  "III" : 3,
  "IV"  : 4,
  "V"   : 5,
  "VI"  : 6,
  "VII" : 7,
  "VIII": 8,
  "IX"  : 9,
  "X"   : 10,
  "XI"  : 11,
  "XII" : 12,
};

const arr = ["II-A", "II-B", "I-A", "IV-A", "IV-B"];

arr.sort((a, b) => {
  const [mainA, secondaryA] = a.split("-");
  const [mainB, secondaryB] = b.split("-");
  
  if (mainA !== mainB)
    return romanTable[mainA] - romanTable[mainB];
   
  return secondaryA.localeCompare(secondaryB);
});

console.log(arr);

Upvotes: 2

Related Questions