Reputation:
I was wondering if anyone knows a way for regex to detect that there has been a minimum of x digits used.
For example if I put in a number 6 digit number of 111222 but my regex says there must be at least 3 unique numbers this would cause a valid fail.
but if I had 123456 that would pass because there is more than three unique digits used.
Something like (obviously it wont be like bellow.)
/^[0-9]{6}*3$/
non regex way
var telcstart = $('#num').val(),
telc1 = (telcstart.match(/1/g) || []).length,
telc2 = (telcstart.match(/2/g) || []).length,
telc3 = (telcstart.match(/3/g) || []).length,
telc4 = (telcstart.match(/4/g) || []).length,
telc5 = (telcstart.match(/5/g) || []).length,
telc6 = (telcstart.match(/6/g) || []).length,
telc7 = (telcstart.match(/7/g) || []).length,
telc8 = (telcstart.match(/8/g) || []).length,
telc9 = (telcstart.match(/9/g) || []).length,
telc0 = (telcstart.match(/0/g) || []).length,
totaltelc = "a:" + telc1 + " b:" + telc2 + " c:" + telc3 + " d:" + telc4 + "e:" + telc5 + " f:" + telc6 + " g:" + telc7 + " h:" + telc8 + " i:" + telc9 + " j:" + telc0,
finaltelc = (totaltelc.match(/0/g) || []).length;
if (finaltelc <= 8) {
alert('passed');
} else {
alert('failed');
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<input type="number" id="num" value="123451212111">
Upvotes: 2
Views: 829
Reputation: 191
function uniqueDigit(str)
{
var a = 0;
for (var i=0; i<10; i++)
{
(new RegExp( i, 'g')).test(str) && a++;
}
return a
}
console.log(uniqueDigit('10122211100')) // in str
console.log(uniqueDigit(222111333888)) // in int
var a = 123456;
console.log(/^\d{6}$/.test(a) && uniqueDigit(a) > 2) // example
Upvotes: 0
Reputation: 523224
^(?=.*(.)(?!$|.*\1))(?=.*(?!\1)(.)(?!$|.*\2))[0-9]+$
function check(value) {
var res = document.getElementById('result');
if (/^(?=.*(.)(?!$|.*\1))(?=.*(?!\1)(.)(?!$|.*\2))[0-9]+$/.test(value)) {
res.innerText = '✓ OK';
} else {
res.innerText = '✗ No match';
}
}
<p>Enter a number with ≥3 different digits</p>
<p><input type=text onkeyup='check(this.value)'> <span id=result></span></p>
Let's split it up:
^
(?=
.*(.) # Pick any character in the string as group 1
(?!$|.*\1) # Ensure this is not the last character, but is the last unique character
)
(?=
.*(?!\1)(.) # Pick another character in the string as group 2
(?!$|.*\2) # Same condition as above
)
[0-9]+
$
The first condition ensures there is a string like ??1??a
. The second condition ensures a string like ???2?b
, where 1
≠ a
and 2
≠ b
and 1
≠ 2
. From this we can conclude there are at least 3 different characters.
This can be easily generalized to e.g. at least 8 different characters needed:
^
(?=.*(.)(?!$|.*\1))
(?=.*(?!\1)(.)(?!$|.*\2))
(?=.*(?!\1|\2)(.)(?!$|.*\3))
(?=.*(?!\1|\2|\3)(.)(?!$|.*\4))
(?=.*(?!\1|\2|\3|\4)(.)(?!$|.*\5))
(?=.*(?!\1|\2|\3|\4|\5)(.)(?!$|.*\6))
(?=.*(?!\1|\2|\3|\4|\5|\6)(.)(?!$|.*\7))
[0-9]+
$
Because JavaScript only support up to \9
, you can't use this method to check more than 10 different characters. At this point you should really question whether regex is a right tool for this job though 😉.
Upvotes: 1
Reputation: 10512
You actually can do this with a regex, but it'll be very ugly and near-incomprehensible.
Looking at just one case, we can write a regex for a string that contains 0, 1, and at least one number from 2 to 9:
/^0(\d)*1(\d)*[2-9](\d)*$/
For each possible pair of numbers, we would have to write a regex like this ad combine all of them using |
so that we catch all cases.
There are 10*9 = 90 pairs of distinct digits, and for each group there are 2 permutations, totalling 180 groups.
So we would have to do:
/(^0(\d)*1(\d)*[2-9](\d)*$/)|(^0(\d)*2(\d)*(1|[3-9])(\d)*$/)| ... /
Continuing for all 180 groups. That would be a gigantic regex, and would probably take a very long while to compile.
You should do this validation with code instead of running a regex.
EDIT: Apparently, JavaScript regexes have some extended features which make this doable, namely reusing the value captured by a given group. refer to @kennytm's answerr.
Upvotes: 1
Reputation: 785058
Based on negative lookaheads you can ensure a different digit matches three times:
(\d)\d*?((?!\1)\d)\d*?(?!\1|\2)\d+$
(?!\1)
negative lookahead to ensure next match is not same as captured group #1(?!\1|\2)
negative lookahead to ensure next match is not same as captured group #1 and group #2Upvotes: 0