1

I'm trying to write a simple function that converts currency values to a code.

I've managed to do the conversion part with .replace(). See jsfiddle https://jsfiddle.net/j9cdrq73/3/

What I want to do is, replace the 2nd repeating character(s) with letter 'Z'

Edit

After the dot (. decimal point) it should reset. 50000 DIZZZ.IZ NOTE the last IZ* see following examples

        number   => after convert =>final (what it should give)
       ---------    -------------  ----------------------------
 So      50000    =>  DI,III.II  =>  DI,ZZZ.IZ
       2677.99    =>   B,EFF.HH  =>   B,EFZ.HZ
     366666.22    => CEE,EEE.BB  => CEZ,ZZZ.BZ

Current code

    function number_to_code(s) {

    // converting the value to something like 50000.00 to look like currency
    // next replace it with the codes as bellow.

      s = parseFloat(s).toFixed(2).replace(/\d/g, m => ({
        '0': 'I',
        '1': 'A',
        '2': 'B',
        '3': 'C',
        '5': 'D',
        '6': 'E',
        '7': 'F',
        '8': 'G',
        '9': 'H'
      })[m]); 
    
    
    // grouping it with , 
      s = s.replace(/\B(?=(\w{3})+(?!\w))/g, ",");       
     return s;
    }

Better if we can do it all in a single regex to improve efficiency.

Hirantha
  • 33
  • 5

2 Answers2

0

You might use 2 capture groups, with a backreference repeating the char 1 or more times that was captured in group 1.

([A-Z])(\1+)
  • ([A-Z]) Capture group 1, match a char A-Z
  • (\1+) Capture group 2, repeat 1+ the same char that is captured in group 1

Regex demo

In the code, you can add another replacement returning the concatenation of group 1 followed by replacing all the characters with Z from group 2.

function number_to_code(s) {

  // converting the value to something like 50000.00 to look like currency
  // next replace it with the codes as bellow.

  s = parseFloat(s).toFixed(2).replace(/\d/g, m => ({
    '0': 'I',
    '1': 'A',
    '2': 'B',
    '3': 'C',
    '5': 'D',
    '6': 'E',
    '7': 'F',
    '8': 'G',
    '9': 'H'
  })[m]);

  // grouping it with , 
  s = s
    .replace(/([A-Z])(\1+)/g, (_, g1, g2) => {
      return g1 + g2.replace(/./g, "Z")
    })
    .replace(/\B(?=(\w{3})+(?!\w))/g, ",")

  return s;
}

console.log(number_to_code("50000"));
console.log(number_to_code("2677.99"));
console.log(number_to_code("366666.22"));
The fourth bird
  • 154,723
  • 16
  • 55
  • 70
  • Thanks for the fast reply. but I want to keep first letter same and other repeating letters to be replaced. do the same after the (.) (decimal point). DIIIIIIII will look like DIZZZZZZ.IZ – Hirantha Jun 01 '21 at 08:55
  • @Hirantha You can do the replacement of the repeating characters first in that case. See the updated answer. – The fourth bird Jun 01 '21 at 09:26
0
(\d)(\1*)

Maybe this is what you want.

The first group is any digit, the second groups is the repeated digits(if any). Then you replace them separately.

After that group the entire result with ,.

function number_to_code(s) {
  return parseFloat(s).toFixed(2)
    .replace(/(\d)(\1*)/g, (_, digit, repeats) => ({
      '0': 'I',
      '1': 'A',
      '2': 'B',
      '3': 'C',
      '5': 'D',
      '6': 'E',
      '7': 'F',
      '8': 'G',
      '9': 'H'
    })[digit] + ''.padStart(repeats.length, 'Z'))
    .replace(/\B(?=(\w{3})+(?!\w))/g, ",");
}

const numbers = [
  '50000',
  '2677.99',
  '366666.22',
];

const result = numbers.map(number_to_code);

console.log(result);
Hao Wu
  • 17,573
  • 6
  • 28
  • 60