Find Characters with Lazy Matching?

Tell us what’s happening:
I passed the topic with the code I have here, but it didn’t implement the lesson. What was I ‘supposed’ to do?

Your code so far


let text = "<h1>Winter is coming</h1>";
let myRegex = /<h1*>/; // Change this line
let result = text.match(myRegex);

Your browser information:

User Agent is: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/67.0.3396.87 Safari/537.36 OPR/54.0.2952.71.

Link to the challenge:
https://learn.freecodecamp.org/javascript-algorithms-and-data-structures/regular-expressions/find-characters-with-lazy-matching

Yup, as lost as you, would like to help but i don’t know as well…
but it seems to me that they just wanted you to give an empty string or to know that it has a h1 tag… still no clue

I had tried to explain to some degree what was supposed to be done. Hopefully this helps:

The point isn’t about the tag, it’s about what the regex will select. Suppose you wanted a regex that simply matches the first tag it encounters, and stops there. that is what the let myRegex = /<.*?>/; line does. Adding the question mark prior to the closing tag limits the regex match to the nearest matching symbol. If instead we had stuck with let myRegex = /<.*>/;, we would have selected everything in the line.
This lesson is about greedy matching (getting the MOST) versus lazy matching (getting the least possible).
In the case above, /<.*?>/ will match any tag, doesn’t matter if its an h1 or a custom tag. doesn’t care. But ONLY the tag, whether an opening or closing tag. Just the one.

I don’t know, I guess I’m just confused as to why you’re confused.

1 Like

Allow me to practice my understanding by explaining this in as much detail as I possibly can:

I also agree this test passes too easily, and although I figured out by myself what the “lesson” was to be learned here (understanding how * behaves vs *?).

Here is the original setup:

let text = "<h1>Winter is coming</h1>";
let myRegex = /<.*>/; // Change this line
let result = text.match(myRegex);

So what it is trying to teach is the default ‘greedy’ behavior vs the ‘?’ addition which makes it ‘lazy’.

Try to solve this without searching for the entire <h1> tag, and instead try to get regex to select only the text between the first ‘<’ and the FIRST ‘>’.

With the provided regex /<.*>/, the regex is saying first find ‘<’ then, after any number of any character inside, the final character should be ‘>’. The ‘greedy’ behavior will first find <h1> but unlike lazy behavior, will keep looking to see if there is another ‘>’ character. Since the string ends with a ‘>’ in the closing </h1> tag, it takes the ‘greedier’ string, which is the entire <h1>Winter is coming</h1>.

The goal should be to use virtually the same regex, ONLY add the ‘lazy’ instruction (’?’) so regex will stop after it meets the conditions for the first time (finding the FIRST closing ‘>’), and be ‘lazy’ and stop after the condition is met, even if other solutions are possible.

Solution below:

CAN’T GET SPOILER TAGS TO WORK FOR THE LIFE OF ME, SO SPOILERS BELOW!!

myRegex = /<.*?>/;

This regex is nearly identical to the one provided (myRegex = /<.*>/) except it stops immediately when it finds a string that starts with ‘<’, finds 0 or more of any characters, then ends with ‘>’. Remember ‘.’ is a wildcard for any character in regex, and the lazy marker should be applied to it, not after the closing ‘>’ since you want to be lazy about the number of ‘any characters’ it finds between the arrow brackets.

3 Likes

exactly right. Well said. And “greedy” searches will usually go from the first < to the LAST > (not a random end character, but the last found in the string, returning the longest possible result).