Use regular expression test with caution! !

1. Background

In the dead of night, the front end of the company couldn’t move and planned to leave work!

The project manager immediately stopped him and said: Sir, add another requirement for me, and it will be released tomorrow!

Front-end bearer: Get out, I’m going back to sleep!

Project Manager: If you help me with this, I will introduce you to a girlfriend this weekend!

Although the front-end handle is good, but until now I don’t have a girlfriend. Hearing what the project manager said, my eyes shine! Said: What problem, get it tonight.

The project manager secretly said in his heart: You boy, you really like this! He turned around and pulled the front end to his workstation and said: I have a set of data here, which is a two-dimensional array, but there are some dirty data in it. I want to remove these dirty data and send it to the back end. So add a data cleaning function! Look, let me draw for you:

const arr = [
  ['123','456','789'],
  ['234','-','567'],
  ['890','*','?'],
]

When sending to the backend, it is necessary to filter out these non-numbers. This is urgent, so please help me to make it urgent tonight.

The front end thought to himself, such a simple function, can it be done in minutes! Isn’t the girlfriend going to get it right away, haha! Then he was eloquent, and the operation was as fierce as a tiger, and wrote the following code!

const arr = [
  ['123','456','789'],
  ['234','-','567'],
  ['890','*','?'],
]

const reg = /[^0-9]/g

const clearData = (arr: string[][])=>{<!-- -->
  const rowLen = arr. length;
  for(let i = 0 ; i< rowLen ; i ++ ){<!-- -->
    const columnLen = arr[i].length;
    for(let j = 0;j< columnLen;j ++ ){<!-- -->
      if(reg.test(arr[i][j])){<!-- -->
        arr[i][j] = ""
      }
    }
  }
  return arr;
}

The front end took a look at the code I wrote again, and said to myself: It is quite elegant, especially considering that the access to . The outer layer, the performance is also good. Turning around and shouting: I finished writing, what about that, Miss Sister, push me on WeChat!

The project manager was playing Glory of Kings, and said unhappily: Here it is, it’s good to be so soon, as expected of the front end, but don’t worry, I’ll verify it first!

The front-end is holding the handle and thinking in his heart that this code can still make mistakes, and you are the only one who has too many things! Then he said out of politeness: "All right, all right!" you try it.

After the project manager clicked to clean, he said in a very unsatisfactory manner: Why do you have to clean it many times every time to finish cleaning it all!

The front end carried the handle and said: How is it possible, let me see

// run returns the result

[
  ['123','456','789'],
  ['234','','567'],
  ['890','','?'], // how come there is still one fish that slipped through the net, his sister
]

The front end carried the handle and checked its own code again;

const arr = [
  ['123','456','789'],
  ['234','-','567'],
  ['890','*','?'],
]

const reg = /[^0-9]/g

const clearData = (arr: string[][])=>{<!-- -->
  const rowLen = arr. length;
  for(let i = 0 ; i< rowLen ; i ++ ){<!-- -->
    const columnLen = arr[i].length;
    for(let j = 0;j< columnLen;j ++ ){<!-- -->
      if(reg.test(arr[i][j])){<!-- -->
        arr[i][j] = ""
      }
    }
  }
  return arr;
}

There is no problem with this code seeing through the sky! Traverse each element and replace it if it meets the regularity. Such a simple logic can still go wrong! Looking at the contemptuous eyes of the project manager, the front-end leader blushed instantly. This is no longer a matter of introducing a girlfriend. Whatever you say today, you have to prove your status as the front-end leader.

He immediately said: Project manager, you go back first, I don’t care about my girlfriend, you will see a complete and problem-free function tomorrow morning! After that, he checked the documents on his own.

After a few hours, the front-end took the time to study almost all the regular documents and realized it.

2. Think

The following is the inner process of carrying the handle on the front end:

It turned out to be because of this lastIndex problem, where do we start?

When we create a regular expression using literals, it is equivalent to initializing an object. There is a property called lastIndex on this object. Let's take a look at its definition.

  • This property will only work if the regular expression uses the "g" flag for global search or the "y" flag for sticky search;
  • If ?regexp.test? and ?regexp.exec? match successfully, lastIndex? will be set to the next a location.
  • If ?regexp.test? and ?regexp.exec? fail to match, lastIndex? will be set to 0;

Let's look at an example:

const reg = /[^0-9]/g;

reg.test('a') // true

reg.lastIndex // 1

reg.test('a') // false

reg.lastIndex // 0

It can be found that for the same regular expression, there will be different results when matching the same string. The core reason is that the lastIndex of the regular expression is constantly changing, and the next match starts from the position of lastIndex , so different results will occur.

There is also the exec method that will also have this feature.

const reg = /[^0-9]/g;

reg.exec('a') // ['a', index: 0, input: 'a', groups: undefined]

reg.lastIndex // 1

reg.exec('a') // null

reg.lastIndex // 0

So be careful when using the above method in the future. How to solve the problem of the project manager?

3. Solution

Method 1: Use the latest regular expressions every time

const arr = [
  ['123','456','789'],
  ['234','-','567'],
  ['890','*','?'],
]

const clearData = (arr: string[][])=>{<!-- -->
  const rowLen = arr. length;
  for(let i = 0 ; i< rowLen ; i ++ ){<!-- -->
    const columnLen = arr[i].length;
    for(let j = 0;j< columnLen;j ++ ){<!-- -->
      if(/[^0-9]/g.test(arr[i][j])){<!-- -->
        arr[i][j] = ""
      }
    }
  }
  return arr;
}

This method can be done, but every loop creates a regular expression, the performance will not be very good!

Method 2: Remove the modifier g

const arr = [
  ['123','456','789'],
  ['234','-','567'],
  ['890','*','?'],
]

const reg = /[^0-9]/

const clearData = (arr: string[][])=>{<!-- -->
  const rowLen = arr. length;
  for(let i = 0 ; i< rowLen ; i ++ ){<!-- -->
    const columnLen = arr[i].length;
    for(let j = 0;j< columnLen;j ++ ){<!-- -->
      if(reg.test(arr[i][j])){<!-- -->
        arr[i][j] = ""
      }
    }
  }
  return arr;
}

There is no problem for this business scenario, but if the requirement is changed to replace the wrong character with a specific character for each string element, it will not work. At this time, modifiers must be used to match the string as a whole. So this approach is also limited.

Method 3: Compulsory matching from the starting position each time

const arr = [
  ['123','456','789'],
  ['234','-','567'],
  ['890','*','?'],
]

const reg = /[^0-9]/g

const clearData = (arr: string[][])=>{<!-- -->
  const rowLen = arr. length;
  for(let i = 0 ; i< rowLen ; i ++ ){<!-- -->
    const columnLen = arr[i].length;
    for(let j = 0;j< columnLen;j ++ ){<!-- -->
      reg.lastIndex = 0;
      if(reg.test(arr[i][j])){<!-- -->
        arr[i][j] = ""
      }
    }
  }
  return arr;
}

This method is good, that is, you don’t need to create a new regular expression every time, and you can also perform global matching for each unit string. It should be the best solution!

4. End

The front end took the lead and finally sorted out the code, tested the function and there was no problem, then silently packed the schoolbag and found that it was already 2 o'clock in the morning!

He once again defended his spirit of carrying the front end to death, but he knew what kind of front end he was! A simple regex. He has been working for so long, and he only figured out this lastIndex today, so there are no programmers who can handle it. It is nothing more than continuous learning. The most important thing is to keep a learning heart all the time!

Walking on the street alone, he felt very cold, and suddenly the phone rang! He saw that the project manager pushed him a WeChat message and sent a message:

Wechat push to you, this is my cousin, I see that you work very seriously, and you are also dedicated to technology, take the opportunity, brother can only help you here!

Yes, this time, the front-end leader must seize the opportunity, come on!

5. Author's recent articles

"Build a personal website with fragmented time" "Develop a browser plug-in from 0 to 1" "Communication of Chrome plug-in (V3 version)"

syntaxbug.com © 2021 All Rights Reserved.