skip to Main Content

I have this function
this function has to detect numeric and nonnumeric numbers like ‘one’ or ‘1’;
but the trickiest part is when when you have something like ‘twone‘ in there you have both ‘one’ and ‘two’, and o is common for solving this problem.

I decided not to increase the pointer ‘i’ to keep the last word and check again that is there any numbers starts with ‘o’,

but in this case ‘twothree’; it fails.

because you keep ‘o’ and but the next letter is ‘t’ and there is no numbers starts with ‘ot’,
So in this case I need to increase pointer ‘i’ because I have ‘three’

this is my code

function detectNumbers(input) {
    const wordToNumbers = new Map([
        ['zero', '0'],
        ['one', '1'],
        ['two', '2'],
        ['three', '3'],
        ['four', '4'],
        ['five', '5'],
        ['six', '6'],
        ['seven', '7'],
        ['eight', '8'],
        ['nine', '9']
    ]);

    let outStr = '';
    let myStr = '';
   
    let i = 0;
while (i < input.length) {
    if (!isNaN(Number(input[i]))) {
        myStr = ''; // Reset myStr if the character is a number
        outStr += input[i];
        i++;
    } else {
        myStr += input[i];
    
        let keyFound = false; 
        for (const key of wordToNumbers.keys()) {
            if (key.startsWith(myStr)) {
                keyFound = true; // Set flag to true if a key is found
                i++;
                if (wordToNumbers.has(myStr)) {
                    outStr += wordToNumbers.get(myStr);
                    myStr = '';
                    i--;
                    break; // Exit the loop after finding a word and getting a number
                }else break;
            }
        }

        if (!keyFound) {
            myStr = ''; // Reset myStr if no key is found
            i++;
        }
    }
}
    
    const result = outStr.length > 0 ? outStr[0] + outStr[outStr.length - 1] : outStr[0] + outStr[0];
    
    return parseFloat(result);
    
}
detectNumbers('eightwothree')

3

Answers


  1. function detectNumbers(input) {
    const wordToNumbers = [
        ['zero', '0o'],
        ['one', 'o1e'],
        ['two', 't2o'],
        ['three', 't3e'],
        ['four', '4'],
        ['five', '5e'],
        ['six', '6'],
        ['seven', '7n'],
        ['eight', 'e8t'],
        ['nine', 'n9e']
    ];
    for(let i=0;i<10;++i)
        input = input.replaceAll(wordToNumbers[i][0],wordToNumbers[i][1]);
    input = input.replace(/[^d.-]/g, '');
    return parseFloat(input);
    

    }
    detectNumbers(‘8oneightwone’);

    Login or Signup to reply.
  2. Another approach is checking all words inside the string and then sorting them by index:

    function detectNumbers(input) {
        let results = []
        const wordToNumbers = new Map([
            ['zero', '0'],
            ['one', '1'],
            ['two', '2'],
            ['three', '3'],
            ['four', '4'],
            ['five', '5'],
            ['six', '6'],
            ['seven', '7'],
            ['eight', '8'],
            ['nine', '9']
        ]);
        const words = ['zero','one','two','three','four','five','six','seven','eight','nine']
    
        words.forEach(word => {
          // Check if the word is found
          if (input.includes(word)) {
            // Get the index
            let index = input.indexOf(word)
            results.push({index, word})
          }
        })
        
        // Sort by index
        results.sort((a,b) => a.index - b.index)
        
        // Map to numbers
        let mapped = results.map(r => wordToNumbers.get(r.word))
        
        // Join the result
        return mapped.join('')
        
    }
    console.log(detectNumbers('eightwothree'))
    console.log(detectNumbers('twone'))
    Login or Signup to reply.
  3. Build a tree of characters for numbers and walk through it:

    const wordToNumbers = new Map([['zero', '0'], ['one', '1'], ['two', '2'], ['three', '3'], ['four', '4'], ['five', '5'], ['six', '6'], ['seven', '7'], ['eight', '8'], ['nine', '9']]);
    
    let tree = {};
    
    // build a tree of characters being nodes and digits being leaves
    // then we could navigate character by character in the tree and find the corresponding digit if the path isn't broken while walking
    for (const [k,v] of wordToNumbers.entries()) {
        let node = tree;
        for (const c of k.slice(0, -1)) {
            node = (node[c] ??= {});
        }
        node[k.at(-1)] = parseInt(v);
    }
    // that's how our tree looks
    console.log(JSON.stringify(tree));
    
    function detectNumbers(input) {
      let out = '';
      // we use 2 arrays with current nodes and next iteration nodes 
      // we mutate arrays and don't resize/recreate them for speed
      // the both arrays should contain the root node so we could start from the root with each character in the input string
      let curr = [tree], currLen = 1, next = [tree], nextLen = 1;
      
      // walk through characters in the provided string
      for (const c of input) {
          // if the character is a digit, just add it to the result and continue with the next character
          if(c >= 0 && c <=9){
            out += c;
            continue;
          }
          // analyze the current nodes (initially just the root one)
          // and if the current character is found in them, collect the next iteration nodes
          for (let i = 0; i < currLen; i++) {
              const node = curr[i];
              if (c in node) { // we found the current input string's character in a node
                  // if it's a number - add it to the result (we found our digit (leaf))
                  if (typeof node[c] === 'number') {
                      out += node[c];
                      continue;
                  }
                  // add the found node for the next iteration
                  next[nextLen++] = node[c];
              }
          }
          // swap current and next nodes to avoid creating new arrays
          [curr, currLen, next, nextLen] = [next, nextLen, curr, 1];
      }
      return out;
    }
    console.log(detectNumbers('eightwothree'));
    console.log(detectNumbers('twone'));
    console.log(detectNumbers('threeight4'));
    console.log(detectNumbers('twoneightwo5nineight'));
    .as-console-wrapper{ inset: 0 }
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search