Lesson Wednesday

Note: In this lesson, we'll refactor our text analyzer application to use regular expressions. This is a further exploration and you are not required to go through this lesson.

In the last lesson, we covered regular expressions in general. Now let's apply them to the text analyzer application we've built. By doing so, we can see just how powerful regular expressions are.

We are going to be exploring some new syntax in this lesson. This is a preview of the next section when we'll learn about JavaScript objects. We can create a new regular expression object like this:

const word = "red";
const regex = new RegExp(word, "gi");

The new keyword creates a new regular expression object. We are not going to discuss objects further until the next section. For now, just be aware that this is the best way to pass a variable into a regular expression.

When we create a new RegExp object, it takes two arguments. The first is the regular expression itself. This can be a variable but it could also be a string as well. The second argument is any flags we want to pass into the regular expression. "gi" means that we want the regular expression to be applied to the entire string and that we want it to be case-insensitive.

So we can do the following in the console:

> const text = "RED red red! Green GREEN green.";
> const word = "red";
> const regex = new RegExp(word, "gi");
> text.match(regex);
["RED", "red", "red"]

You can see where this is going. We can make some of our text analzyer functions much more concise with regular expressions.

Let's take a look:

// Without regex

function numberOfOccurrencesInText(word, text) {
  if (noInputtedWord(word, text)) {
    return 0;
  }
  const wordArray = text.split(" ");
  let wordCount = 0;
  wordArray.forEach(function(element) {
    if (element.toLowerCase().includes(word.toLowerCase())) {
      wordCount++;
    }
  });
  return wordCount;
}

// With regex

function numberOfOccurrencesInText(word, text) {
  if (noInputtedWord(word, text)) {
    return 0;
  }
  const regex = new RegExp(word, "gi");
  return text.match(regex).length;
}

With a regular expression, our function is half as many lines. There is no need to loop at all. We create a regular expression object and store it in regex. Then we simply need to call String.prototype.match() with regex and return the length of the resulting array. Try it out in the console!

Let's demonstrate one more refactor.

// Without regex

function boldPassage(word, text) {
  if (noInputtedWord(word, text)) {
    return "";
  }
  let htmlString = "<p>";
  let textArray = text.split(" ");
  textArray.forEach(function(element, index) {
    if (element.toLowerCase().includes(word.toLowerCase())) {
      htmlString = htmlString.concat("<b>" + element + "</b>");
    } else {
      htmlString = htmlString.concat(element);
    }
    if (index !== (textArray.length - 1)) {
      htmlString = htmlString.concat(" ");
    }
  });
  return htmlString + "</p>";
}

// With regex

function boldPassage(word, text) {
  if (noInputtedWord(word, text)) {
    return "";
  }
  const regexWord = new RegExp(word, "gi");
  const boldedWord = "<b>" + word + "</b>";
  const htmlString = text.replace(regexWord, boldedWord);
  return "<p>" + htmlString + "</p>";
}

Once again, we cut down the number of lines in the function by half. Here we create two variables. regexWord is the regular expression. boldedWord is the replacement - the word plus b tags.

Next, we use String.prototype.replace() to replace all instances of the word with the word plus b tags.

Technically, we could shorten boldPassage() even further:

function boldPassage(word, text) {
  if (noInputtedWord(word, text)) {
    return "";
  }
  return "<p>" + text.replace(new RegExp(word, "gi"), "<b>" + word + "</b>") + "</p>"; 
}

That's pretty hard to read, though. While concise code is great, it should never come at the expense of readability.

To sum up, regular expressions can be fun but they can also be hard to figure out and easy to mess up. Regardless, they are a very powerful tool to have in your developer toolbox.

We can create a RegExp object like this:

const word = "red";
const regex = new RegExp(word, "gi");

This is the best way to pass a variable into a regular expression.

Lesson 30 of 38
Last updated April 7, 2021