Regex to check for 3 same letters in a string? - javascript

I need to create regex which will look for 3 same letters in a string, regardless of the order.
Example:
'aa2ff333' -> false
'aa2a' -> true
'aaa2' -> true
I tried this but it check for consecutive letters:
(.)\1\1
Any advice?

You may use this regex with lookahead:
/([a-zA-Z])(?=(?:.*?\1){2})/
RegEx Demo
RegEx Details:
([a-zA-Z]): Match a letter [a-zA-Z] and capture it in group #1
(?=: Start lookahead
(?:.*?\1){2}: That has at least 2 occurrences of same character as in capture group #1. .*?\1 Matches back-reference \1 after 0 or more of any character. This allows matching repetitions anywhere in input.
): End lookahead

One way is to loop through the string and count occurrence of each character then check if any of character appears for exact three times
let threeChars = (str) => {
let obj = [...str].reduce((op, inp) => {
if (/[a-z]/i.test(inp)) {
op[inp] = op[inp] || 0
op[inp] += 1
}
return op
}, {})
return Object.values(obj).some(v => v === 3)
}
console.log(threeChars('aa2ff333'))
console.log(threeChars('aa2a'))
console.log(threeChars('aaa2'))
P.S:-
You can make it case insensitive by removing the i flag
In case you need to at least 3 character you can change v == 3 to v >= 3

Related

How to check is string has both letter and number in javascript

I have string "JHJK34GHJ456HJK". How to check if this string has both letter and number, doesn't have whitespace, doesn't have special characters like # - /, If has only letter or only number didn't match.
I try with regex below, result is true if string is only number or letter.
const queryLetterNumber = /^[A-Za-z0-9]*$/.test("JHJK34GHJ456HJK");
const input= [
'JHJK34GHJ456HJK',
'JHJKAAGHJAAAHJK',
'123456789012345',
'JHJK34 space JK',
'JHJK34$dollarJK'
];
const regex = /^(?=.*[0-9])(?=.*[A-Za-z])[A-Za-z0-9]+$/;
input.forEach(str => {
console.log(str + ' => ' + regex.test(str));
});
Output:
JHJK34GHJ456HJK => true
JHJKAAGHJAAAHJK => false
123456789012345 => false
JHJK34 space JK => false
JHJK34$dollarJK => false
Explanation:
^ - anchor at beginning
(?=.*[0-9]) - positive lookahead expecting at least one digit
(?=.*[A-Za-z]) - positive lookahead expecting at least one alpha char
[A-Za-z0-9]+ - expect 1+ alphanumeric chars
$ - anchor at end
you should use a regular expression to check for alphanumeric content in the string
/^[a-z0-9]+$/i
The above is a sample that checks for a-z and numbers from 0-9. however, review other options as given here

How to match 2 separate numbers in Javascript

I have this regex that should match when there's two numbers in brackets
/(P|C\(\d+\,{0,1}\s*\d+\))/g
for example:
C(1, 2) or P(2 3) //expected to match
C(43) or C(43, ) // expect not to match
but it also matches the ones with only 1 number, how can i fix it?
You have a couple of issues. Firstly, your regex will match either P on its own or C followed by numbers in parentheses; you should replace P|C with [PC] (you could use (?:P|C) but [PC] is more performant, see this Q&A). Secondly, since your regex makes both the , and spaces optional, it can match 43 without an additional number (the 4 matches the first \d+ and the 3 the second \d+). You need to force the string to either include a , or at least one space between the numbers. You can do that with this regex:
[PC]\(\d+[ ,]\s*\d+\)
Demo on regex101
Try this regex
[PC]\(\d+(?:,| +) *\d+\)
Click for Demo
Explanation:
[PC]\( - matches either P( or C(
\d+ - matches 1+ digits
(?:,| +) - matches either a , or 1+ spaces
*\d+ - matches 0+ spaces followed by 1+ digits
\) - matches )
You can relax the separator between the numbers by allowing any combination of command and space by using \d[,\s]+\d. Test case:
const regex = /[PC]\(\d+[,\s]+\d+\)/g;
[
'C(1, 2) or P(2 3)',
'C(43) or C(43, )'
].forEach(str => {
let m = str.match(regex);
console.log(str + ' ==> ' + JSON.stringify(m));
});
Output:
C(1, 2) or P(2 3) ==> ["C(1, 2)","P(2 3)"]
C(43) or C(43, ) ==> null
Your regex should require the presence of at least one delimiting character between the numbers.
I suppose you want to get the numbers out of it separately, like in an array of numbers:
let tests = [
"C(1, 2)",
"P(2 3)",
"C(43)",
"C(43, )"
];
for (let test of tests) {
console.log(
test.match(/[PC]\((\d+)[,\s]+(\d+)\)/)?.slice(1)?.map(Number)
);
}

I want to count a same letter if the previous letter is the same as the current letter

I have the input string "lorrem ipsssum dollorrrrum" and I want to count the same letter if the current letter is the same as the previous letter and change all the next same letter to the counted that letter,
I want the exact result to look like this:
"lor2emips3umdol2or4um"
I am stuck and I don't know what algorithm should I use, and what keyword to search about this issue in Google :(
The code I've written so far
function countLetter(str) {
return str
.replace(/\s/g, '')
.split('')
.reduce((a, b) => {
return a === b ? b.replace(b, '') : b;
});
}
window.onload = function () {
console.log(countLetter('lorrem ipsssum dollorrrrum'));
}
With a regular expression, you can capture a character and then backreference that same character 1 or more times. Use a replacer function to replace the matched section with the character and the number of characters in the full match:
function countLetter(str) {
return str
.replace(/\s/g, '')
.replace(/(\w)\1+/g, (match, char) => char + match.length);
}
console.log(countLetter('lorrem ipsssum dollorrrrum'));
With an alternation and a capture group, you might also use a single replacement.
Using a ternary operator, check if capture group 1 exists. If it does, return the single word character in group 1 (parameter g1) and append the length of the total match (parameter m).
If there is no group 1, then 1+ or more whitespace chars are matched due to the alternation |, which are replaced with an empty string.
(\w)\1+|\s+
Explanation
(\w)\1+ Capture a single word char in group 1 and repeat that same char 1 or more times which is in backreference \1
| Or
\s+ Match 1+ whitespace chars
const countLetter = s => s
.replace(/(\w)\1+|\s+/g, (m, g1) => g1 ? g1 + m.length : '')
console.log(countLetter('lorrem ipsssum dollorrrrum'));

RegEx complex pattern

I have to write regex that checks if string:
length is 5-15 characters long
has at least 2 uppercase letters
has at least 2 lowercase letters
and has 1 digit
I appreciate any help because I am really stuck on this and don't have any ideas how to solve this.
You can use look ahead to check all conditions, and then match 5 to 15 characters (any), making sure there is nothing else (^ and $):
^(?=(?:.*[A-Z]){2})(?=(?:.*[a-z]){2})(?=.*\d).{5,15}$
^: start of string
(?= ): positive look ahead. Does not grab any characters, but just looks ahead to see if the pattern would be matched
(?: ): make this group non-capturing, i.e. you'll not get it as capturing group that you can reference with $1 or \1 (language dependent)
.*[A-Z]: 0 or more character(s) followed by a capital letter
.*[a-z]: 0 or more character(s) followed by a lower case letter
.*\d: 0 or more character(s) followed by a digit
{2}: previous pattern must match twice
.{5-15}: 5 to 15 characters.
$: end of string
In JavaScript you can test a string against a regular expression with test, for example:
var regex = /^(?=(?:.*[A-Z]){2})(?=(?:.*[a-z]){2})(?=.*\d).{5,15}$/;
console.log(regex.test('a9B1c')); // false, missing capital letter
console.log(regex.test('a9B1cD')); // true
trinctot was right first, but depending on who is using your code and for what, this might be easier to maintain/modify:
var lowerPass = 2 <= (string.match(/[a-z]/g) || []).length;
var upperPass = 2 <= (string.match(/[A-Z]/g) || []).length;
var digitPass = 1 <= (string.match(/[0-9]/g) || []).length;
var lengthPass = 5 <= string.length <= 15;
var stringPass = lowerPass + upperPass + digitPass + lengthPass == 4;
Try this
^([a-z]{2,}[A-Z]{2, }[0-9]{1}+) {5, 15}$

Javascript validation regex for names

I am looking to accept names in my app with letters and hyphens or dashes, i based my code on an answer i found here
and coded that:
function validName(n){
var nameRegex = /^[a-zA-Z\-]+$/;
if(n.match(nameRegex) == null){
return "Wrong";
}
else{
return "Right";
}
}
the only problem is that it accepts hyphen as the first letter (even multiple ones) which i don't want.
thanks
Use negative lookahead assertion to avoid matching the string starting with a hyphen. Although there is no need to escape - in the character class when provided at the end of character class. Use - removed character class for avoiding - at ending or use lookahead assertion.
var nameRegex = /^(?!-)[a-zA-Z-]*[a-zA-Z]$/;
// or
var nameRegex = /^(?!-)(?!.*-$)[a-zA-Z-]+$/;
var nameRegex = /^(?!-)[a-zA-Z-]*[a-zA-Z]$/;
// or
var nameRegex1 = /^(?!-)(?!.*-$)[a-zA-Z-]+$/;
function validName(n) {
if (n.match(nameRegex) == null) {
return "Wrong";
} else {
return "Right";
}
}
function validName1(n) {
if (n.match(nameRegex1) == null) {
return "Wrong";
} else {
return "Right";
}
}
console.log(validName('abc'));
console.log(validName('abc-'));
console.log(validName('-abc'));
console.log(validName('-abc-'));
console.log(validName('a-b-c'));
console.log(validName1('abc'));
console.log(validName1('abc-'));
console.log(validName1('-abc'));
console.log(validName1('-abc-'));
console.log(validName1('a-b-c'));
FYI : You can use RegExp#test method for searching regex match and which returns boolean based on regex match.
if(nameRegex.test(n)){
return "Right";
}
else{
return "Wrong";
}
UPDATE : If you want only single optional - in between words, then use a 0 or more repetitive group which starts with -as in #WiktorStribiżew answer .
var nameRegex = /^[a-zA-Z]+(?:-[a-zA-Z]+)*$/;
You need to decompose your single character class into 2 , moving the hyphen outside of it and use a grouping construct to match sequences of the hyphen + the alphanumerics:
var nameRegex = /^[a-zA-Z]+(?:-[a-zA-Z]+)*$/;
See the regex demo
This will match alphanumeric chars (1 or more) at the start of the string and then will match 0 or more occurrences of - + one or more alphanumeric chars up to the end of the string.
If there can be only 1 hyphen in the string, replace * at the end with ? (see the regex demo).
If you also want to allow whitespace between the alphanumeric chars, replace the - with [\s-] (demo).
You can either use a negative lookahead like Pranav C Balan propsed or just use this simple expression:
^[a-zA-Z]+[a-zA-Z-]*$
Live example: https://regex101.com/r/Dj0eTH/1
The below regex is useful for surnames if one wants to forbid leading or trailing non-alphabetic characters, while permitting a small set of common word-joining characters in between two names.
^[a-zA-Z]+[- ']{0,1}[a-zA-Z]+$
Explanation
^[a-zA-Z]+ must begin with at least one letter
[- ']{0,1} allow zero or at most one of any of -, or '
[a-zA-Z]+$ must end with at least one letter
Test cases
(The double-quotes have been added purely to illustrate the presence of whitespace.)
"Blair" => match
" Blair" => no match
"Blair " => no match
"-Blair" => no match
"- Blair" => no match
"Blair-" => no match
"Blair -" => no match
"Blair-Nangle" => match
"Blair--Nangle" => no match
"Blair Nangle" => match
"Blair -Nangle" => no match
"O'Nangle" => match
"BN" => match
"BN " => no match
" O'Nangle" => no match
"B" => no match
"3Blair" => no match
"!Blair" => no match
"van Nangle" => match
"Blair'" => no match
"'Blair" => no match
Limitations include:
No single-character surnames
No surnames composed of more than two words
Check it out on regex101.

Categories

Resources