Search code examples
javascriptvariablesmultidimensional-arraylet

Why multidimensional array only execute function on every cell?


Problem

I have a Multidimensional Array and a function called conversion().

let variables outside conversion()
will only be executed on every other cell

let variables inside conversion()
works properly but you have to type the exact same variable in every new function

What I'm looking for?

I would like to know why this is happening
If I knew why, then I can fix the problem
But at the moment I don't know why




Works… Kinda

Only executes function on every other cell

let MDA = [
  [ '','','UndefineD','nuLL','trUe','fAlsE','TruE','FalSe','NaN','NAN'],
  [ '1', '2', '3', '4', '5', 'TRUE', 'FALSE', '8', '9', '10' ],
  [ 'a', 'TrUe', 'FaLsE', 'd', 'e', 'f', 'g', 'h', 'i', 'j' ]
],
    regComma = /\b(,")(.*?(?:(?!\b,".*",).)*)(",)/g,
    regNumber = /^((\s+)?((-)|\.)?)?[\d\.]+(\s+)?$/g,
    regBoolean = /^(\s+)?(true|false)(\s+)?$/gi,
    regUndefined = /^(\s+)?(undefined|null)(\s+)?$/gi,
    regNaN = /^(\s)?nan(\s)?$/gi;

function conversion(str) {
  if (regNumber.test(str)) {return parseInt(str);}
  if (regBoolean.test(str)) {return /t/i.test(str)?true:false;}
  if (regUndefined.test(str)) {return /d/i.test(str)?undefined:null;}
  if (regNaN.test(str)) {return NaN;}
  return str;
}


for(var i = 0; i < MDA.length; i++) {
    let cube = MDA[i];
    for(var j = 0; j < cube.length; j++) {
    let cell = cube[j],
    	convert = conversion(cell);
      MDA[i][j] = convert;
    }
}

console.log(MDA)



Works Properly

Inefficient due to me having to write variables
into each function I want preformed on each cell.

let MDA = [
  [ '','','UndefineD','nuLL','trUe','fAlsE','TruE','FalSe','NaN','NAN'],
  [ '1', '2', '3', '4', '5', 'TRUE', 'FALSE', '8', '9', '10' ],
  [ 'a', 'TrUe', 'FaLsE', 'd', 'e', 'f', 'g', 'h', 'i', 'j' ]
];

function conversion(str) {
  let regComma = /\b(,")(.*?(?:(?!\b,".*",).)*)(",)/g,
      regNumber = /^((\s+)?((-)|\.)?)?[\d\.]+(\s+)?$/g,
      regBoolean = /^(\s+)?(true|false)(\s+)?$/gi,
      regUndefined = /^(\s+)?(undefined|null)(\s+)?$/gi,
      regNaN = /^(\s)?nan(\s)?$/gi;
  if (regNumber.test(str)) {return parseInt(str);}
  if (regBoolean.test(str)) {return /t/i.test(str)?true:false;}
  if (regUndefined.test(str)) {return /d/i.test(str)?undefined:null;}
  if (regNaN.test(str)) {return NaN;}
  return str;
}


for(var i = 0; i < MDA.length; i++) {
    let cube = MDA[i];
    for(var j = 0; j < cube.length; j++) {
    let cell = cube[j],
    	convert = conversion(cell);
      MDA[i][j] = convert;
    }
}

console.log(MDA)



What I've Tried

Placed the let variables outside conversion()
Created new let variables referenced to outside variables
But it only works on every other cell

let MDA = [
  [ '','','UndefineD','nuLL','trUe','fAlsE','TruE','FalSe','NaN','NAN'],
  [ '1', '2', '3', '4', '5', 'TRUE', 'FALSE', '8', '9', '10' ],
  [ 'a', 'TrUe', 'FaLsE', 'd', 'e', 'f', 'g', 'h', 'i', 'j' ]
],
  regComma = /\b(,")(.*?(?:(?!\b,".*",).)*)(",)/g,
  regNumber = /^((\s+)?((-)|\.)?)?[\d\.]+(\s+)?$/g,
  regBoolean = /^(\s+)?(true|false)(\s+)?$/gi,
  regUndefined = /^(\s+)?(undefined|null)(\s+)?$/gi,
  regNaN = /^(\s)?nan(\s)?$/gi;

function conversion(str) {
  let r1 = regComma,
      r2 = regNumber,
      r3 = regBoolean,
      r4 = regUndefined,
      r5 = regNaN;
  if (r2.test(str)) {return parseInt(str);}
  if (r3.test(str)) {return /t/i.test(str)?true:false;}
  if (r4.test(str)) {return /d/i.test(str)?undefined:null;}
  if (r5.test(str)) {return NaN;}
  return str;
}


for(var i = 0; i < MDA.length; i++) {
    let cube = MDA[i];
    for(var j = 0; j < cube.length; j++) {
    let cell = cube[j],
    	convert = conversion(cell);
      MDA[i][j] = convert;
    }
}

console.log(MDA)


Solution

  • From the documentation

    test() called multiple times on the same global regular expression instance will advance past the previous match.

    If the regex has the global flag set, test() will advance the lastIndex of the regex. A subsequent use of test() will start the search at the substring of str specified by lastIndex (exec() will also advance the lastIndex property). It is worth noting that the lastIndex will not reset when testing a different string.

    Hence was causing this behavior. Removing the g from the regex would give your expected behavior.

    const MDA = [
      [ '','','UndefineD','nuLL','trUe','fAlsE','TruE','FalSe','NaN','NAN'],
      [ '1', '2', '3', '4', '5', 'TRUE', 'FALSE', '8', '9', '10' ],
      [ 'a', 'TrUe', 'FaLsE', 'd', 'e', 'f', 'g', 'h', 'i', 'j' ]
    ];
      
    const  regComma = /\b(,")(.*?(?:(?!\b,".*",).)*)(",)/,
        regNumber = /^((\s+)?((-)|\.)?)?[\d\.]+(\s+)?$/,
        regBoolean = /^(\s+)?(true|false)(\s+)?$/i,
        regUndefined = /^(\s+)?(undefined|null)(\s+)?$/i,
        regNaN = /^(\s)?nan(\s)?$/i;
    
    function conversion(str) {
      if (regNumber.test(str)) {return parseInt(str);}
      if (regBoolean.test(str)) {return /t/i.test(str)?true:false;}
      if (regUndefined.test(str)) {return /d/i.test(str)?undefined:null;}
      if (regNaN.test(str)) {return NaN;}
      return str;
    }
    
    
    for(var i = 0; i < MDA.length; i++) {
        const cube = MDA[i];
        for(var j = 0; j < cube.length; j++) {
        const cell = cube[j],
        	convert = conversion(cell);
          MDA[i][j] = convert;
        }
    }
    
    console.log(MDA);

    Great Question. Thanks for it.