Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

The regular expression doesn't work equal in different code even being the same input

Tags:

javascript

I'm creating a code, a part of this code uses a regular expression which is:

var ex = "122", checker = /(\d)\1{1,}/g,
    c = pattern.test(+ex);
if(c) console.log(`works.`);

My goal is to check if there is a repeated number.

The problem arises when I use the above snippet in a larger section of code. I have the same input at the above snippet, but in the below code, the regex isnt work

Here is the code:

function almostIncreasingSequence(sequence) {
    var clone = [].concat(sequence),
        l = clone.length,
        pattern = /(\d)\1{2,}/ig;
    if (pattern.test(clone)) {
        return false;
    }

    var sorted = sequence.splice(0).sort(function(a, b) {
            return a - b;
        }),
        element, finder, checker = /(\d)\1{1,}/g;
        
    for (var i = 0; i < l; ++i) {
        element = clone[i];
        finder = sorted.indexOf(element);
        clone.splice(i, 1);
        sorted.splice(finder, 1);
        if (clone.join("") === sorted.join("") && !checker.test(+clone.join(""))) {
            /*
            In the conditional above, i use the regex
            */
            console.log(`
            Same input: ${+clone.join("")}
            
            PD: This message, it should not be shown, since the conditional should not have been true,
            `);
            return true;
        } else {
            clone.splice(i, 0, element);
            sorted.splice(finder, 0, element);
        }
    }
    return false;
}
console.log(almostIncreasingSequence([1, 2, 1, 2]))

So in the first snippet code, the regex return true, but in the second snippet code, or the regex is bad or the negation isn't works, because i'm negating the result of regex, because the regex in the second snippet code have the same input as the first, so the negation of true is false .

like image 311
Eduardo Campos Avatar asked Dec 06 '17 21:12

Eduardo Campos


People also ask

Is regular expression same in all programming languages?

Regular expression synax varies slightly between languages but for the most part the details are the same. Some regex implementations support slightly different variations on how they process as well as what certain special character sequences mean.

How do you know if two regular expressions are equal?

We say that two regular expressions R and S are equivalent if they describe the same language. In other words, if L(R) = L(S) for two regular expressions R and S then R = S.

What is the regular expression we have to use to match any one character not between the brackets is?

Explanation: The [^…] character class is used to match or draw any one character not between the brackets.


1 Answers

The issue is that you are using /g in your Regexp - when this is used, and the regex is executed multiple times, it will always begin where it left off last time.

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/RegExp/lastIndex

This property is set only if the regular expression instance used the "g" flag to indicate a global search. The following rules apply:

If lastIndex is greater than the length of the string, test() and exec() fail, then lastIndex is set to 0.

If lastIndex is equal to the length of the string and if the regular expression matches the empty string, then the regular expression matches input starting at lastIndex.

If lastIndex is equal to the length of the string and if the regular expression does not match the empty string, then the regular expression mismatches input, and lastIndex is reset to 0.

Otherwise, lastIndex is set to the next position following the most recent match.

You can see this is happening by logging checker.lastIndex before you do checker.test, and you will see that when it fails, lastIndex is not 0.

function almostIncreasingSequence(sequence) {
    var clone = [].concat(sequence),
        l = clone.length,
        pattern = /(\d)\1{2,}/ig;
    if (pattern.test(clone)) {
        return false;
    }

    var sorted = sequence.splice(0).sort(function(a, b) {
            return a - b;
        }),
        element, finder, checker = /(\d)\1{1,}/g;
        
    for (var i = 0; i < l; ++i) {
        element = clone[i];
        finder = sorted.indexOf(element);
        clone.splice(i, 1);
        sorted.splice(finder, 1);
        console.log(checker.lastIndex)
        if (clone.join("") === sorted.join("") && !checker.test(+clone.join(""))) {
            /*
            checker.test(+clone.join("")) <-- HERE IS THE REGEX
            */
            console.log( `The number is ${+clone.join("")} 
  and the regex return: ${checker.test(+clone.join(""))}, 
  so, if the regex return true, the negation operator, isnt work ? because im negating the returned value from the regex !checker.test
  `); // FALSE ? Why... ??
            return true;
        } else {
            clone.splice(i, 0, element);
            sorted.splice(finder, 0, element);
        }
    }
    return false;
}
console.log(almostIncreasingSequence([1, 2, 1, 2]))

Or, to use your first "working" code:

var ex = "122", checker = /(\d)\1{1,}/g,
    c = checker.test(+ex);
if(c) console.log(`works.`);
c = checker.test(+ex);
if(c) console.log(`works.`);

And it will only print works once, because you are checking it more than once and it has a /g on the Regexp.

like image 155
dave Avatar answered Oct 12 '22 13:10

dave