user10288182
user10288182

Reputation:

why condition is always true in javascript?

Could you please tell me why my condition is always true? I am trying to validate my value using regex.i have few conditions

  1. Name should not contain test "text"
  2. Name should not contain three consecutive characters example "abc" , "pqr" ,"xyz"
  3. Name should not contain the same character three times example "aaa", "ccc" ,"zzz"

I do like this

https://jsfiddle.net/aoerLqkz/2/

var val = 'ab dd'

if (/test|[^a-z]|(.)\1\1|abc|bcd|cde|def|efg|fgh|ghi|hij|ijk|jkl|klm|lmn|mno|nop|opq|pqr|qrs|rst|stu|tuv|uvw|vwx|wxy|xyz/i.test(val)) {
                       alert( 'match')
                    } else {
   alert( 'false')
   }

I tested my code with the following string and getting an unexpected result

  1. input string "abc" : output fine :: "match"
  2. input string "aaa" : output fine :: "match"
  3. input string "aa a" : **output ** :: "match" why it is match ?? there is space between them why it matched ????

    input string "sa c" : **output ** :: "match" why it is match ?? there is different string and space between them ????

Upvotes: 2

Views: 215

Answers (5)

forgivenson
forgivenson

Reputation: 4435

The issue is the [^a-z]. This means that any string that has a non-letter character anywhere in it will be a match. In your example, it is matching the space character.

The solution? Simply remove |[^a-z]. Without it, your regex meets all three criteria.

  1. test checks if the value contains the word 'test'.
  2. abc|bcd|cde|def|efg|fgh|ghi|hij|ijk|jkl|klm|lmn|mno|nop|opq|pqr|qrs|rst|stu|tuv|uvw|vwx|wxy|xyz checks if the value contains three sequential letters.
  3. (.)\1\1 checks if any character is repeated three times.

Complete regex:

/test|(.)\1\1|abc|bcd|cde|def|efg|fgh|ghi|hij|ijk|jkl|klm|lmn|mno|nop|opq|pqr|qrs|rst|stu|tuv|uvw|vwx|wxy|xyz/i`

I find it helpful to use a regex tester, like https://www.regexpal.com/, when writing regular expressions.

NOTE: I am assuming that the second criteria actually means "three consecutive letters", not "three consecutive characters" as it is written. If that is not true, then your regex doesn't meet the second criteria, since it only checks for three consecutive letters.

Upvotes: 1

David Lemon
David Lemon

Reputation: 1560

I would not do this with regular expresions, this expresion will always get more complicated and you have not the possibilities you had if you programmed this.

The rules you said suggest the concept of string derivative. The derivative of a string is the distance between each succesive character. It is specially useful dealing with password security checking and string variation in general.

const derivative = (str) => {
  const result = [];
  for(let i=1; i<str.length; i++){
    result.push(str.charCodeAt(i) - str.charCodeAt(i-1));
  }
  return result;
  };

//these strings have the same derivative: [0,0,0,0]
console.log(derivative('aaaaa'));
console.log(derivative('bbbbb'));

//these strings also have the same derivative: [1,1,1,1]
console.log(derivative('abcde'));
console.log(derivative('mnopq'));

//up and down: [1,-1, 1,-1, 1]
console.log(derivative('ababa'));

With this in mind you can apply your each of your rules to each string.

//    Rules:
// 1.   Name should not contain test "text"
// 2.   Name should not contain three consecutive characters example "abc" , "pqr" ,"xyz"
// 3.   Name should not contain the same character three times example "aaa", "ccc" ,"zzz"

const derivative = (str) => {
  const result = [];
  for(let i=1; i<str.length; i++){
    result.push(str.charCodeAt(i) - str.charCodeAt(i-1));
  }
  return result;
  };
  
const arrayContains = (master, sub) => 
    master.join(",").indexOf( sub.join( "," ) ) == -1;


const rule1 = (text) => !text.includes('text');

const rule2 = (text) => !arrayContains(derivative(text),[1,1]);

const rule3 = (text) => !arrayContains(derivative(text),[0,0]);

const testing = [
  "smthing textual",'abc','aaa','xyz','12345',
  '1111','12abb', 'goodbcd', 'weeell'
];

const results = testing.map((input)=>
  [input, rule1(input), rule2(input), rule3(input)]);

console.log(results);

Upvotes: 0

Matt.G
Matt.G

Reputation: 3609

Based on the 3 conditions in the post, the following regex should work.

Regex: ^(?:(?!test|([a-z])\1\1|abc|bcd|cde|def|efg|fgh|ghi|hij|ijk|jkl|klm|lmn|mno|nop|opq|pqr|qrs|rst|stu|tuv|uvw|vwx|wxy|xyz).)*$

Demo

Upvotes: -1

TimWolla
TimWolla

Reputation: 32701

there is space between them why it matched ????

Because of the [^a-z] part of your regular expression, which matches the space:

> /[^a-z]/i.test('aa a');
true

Upvotes: 5

Quentin
Quentin

Reputation: 943605

The string sa c includes a space, the pattern [^a-z] (not a to z) matches the space.

Possibly you want to use ^ and $ so your pattern also matches the start and end of the string instead of looking for a match anywhere inside it.

Upvotes: 9

Related Questions