How to check if a digit appears more than once in a number (anywhere within it)?
Example input numbers:
1, 10, 11, 1010, 1981
Output should tell which of them has any repeated digits:
false, false, true, true, true
Publihsed all the good answers given in a jsperf page
How to check if a digit appears more than once in a number (anywhere within it)?
Example input numbers:
1, 10, 11, 1010, 1981
Output should tell which of them has any repeated digits:
false, false, true, true, true
Publihsed all the good answers given in a jsperf page
Share Improve this question edited May 22, 2022 at 20:37 vsync asked Feb 28, 2017 at 9:13 vsyncvsync 130k59 gold badges340 silver badges421 bronze badges7 Answers
Reset to default 5I think the fastest way would be a RegExp test. You can use it to get a quick true or false on whether there is a repeat, and it's pact enough to use in conditional operators. Here's an example that'd work with numbers and strings of numbers.
function hasRepeatingdigits(N) {
return (/([0-9]).*?\1/).test(N)
}
console.log(
[1, 10, 11, 1010, 1981, 12345678901, 123456789].map(hasRepeatingdigits)
)
(Edit -Isaac B)
Here's a breakdown of how the RegExp works:
- The
[0-9]
creates a list of single characters between 0 and 9 to be matched. - Adding the parentheses
([0-9])
defines this list as the first capture group. These parens would not be needed if you were only searching for a char and didn't need the RegExp to perform a subsequent action. (i.e. /[0-9]/ is all you need to find the first index of a char 0 through 9 in a string, or true in a RegExp test) - The
.
matches any single char - except for line terminators. Adding the lazy quantifier*?
matches between 0 and infinity times, as few time as possible. - The
\1
matches the same text as most recently matched by the first capture group
In summary: /([0-9]).*?\1/
is a regular expression that iterates through a string looking for each char 0 through 9 and returning a match the first time a match is found to the char currently in the first capture group.
In the string '123432'
, this RexExp would return a full match: '2343'
on capture group 1: '2'
.
RegExp.prototype.test() searches a string using the provided RegExp and returns true if the RegExp return a match, else it returns false. This could easily be modified to find a duplicate letter char as well using /([A-Za-z]).*?\1/).test(N)
.
Beyond the very useful MDN section on RegExp, I highly remend people working to get more fortable with them to check out this RegularExpressions101 tool.
function checkForRepeatingDigits(N){
var arr = (''+N).split(''),
result = arr.filter((elem, i) => arr.indexOf(elem) == i);
return result.length != (''+N).length;
}
// Or
function checkForRepeatingDigits(N){
return [...new Set((''+N).split(''))].length != (''+N).length;
}
console.log([1, 10, 11, 1010, 1981].map(checkForRepeatingDigits))
You could use a check with Array#indexOf
and Array#lastIndexOf
.
function check(a, _, aa) {
return aa.indexOf(a) !== aa.lastIndexOf(a);
}
console.log([1, 10, 11, 1010, 1981].map(a => a.toString().split('').some(check)));
Short solution using Array.prototype.map()
and String.prototype.match()
function:
function checkForRepeatingDigits(N) {
return N.map(function (v) {
return [v, Boolean(String(v).match(/(\d)\d*?\1/g))];
});
}
console.log(checkForRepeatingDigits([1, 10, 11, 1010, 1981]));
function repeated(n) {
var digits = [];
var digit;
while (n) {
digit = n % 10;
if (digits[digit]) return true;
digits[digit] = true;
n = Math.floor(n / 10);
}
return false;
}
[1, 10, 11, 1010, 1981].forEach(n => console.log(n, repeated(n)));
This works by first converting the number to a string with N = N + ''
and then checking the result of split()
, which is a String function that crushes a string to smaller parts based on a delimiter.
For example, if I split "aba"
by "b"
, I'll get an array containing ["a", "a"]
. As you can see, if there's one occurrence of "b"
, the length of the returned array is 2
. If there's more, it will be over 2
. This is what I use in my solution.
As a bonus, it works with other types of data, even null
and undefined
. ;)
function check(N) {
for (var N = N + '', i = (N).length; i--;)
if (N.split(N[i]).length > 2)
return true;
return false;
}
[1, 10, 11, 1010, 1981, "abcd23", "aab", "", null, undefined].forEach(num => {
console.log(num, check(num));
});
const isRepeated = (num) => new Set('' + num).size != ~~Math.log10(num) + 1;
[1, 10, 11, 1010, 1981].forEach(n => console.log(n, isRepeated(n)));
JS offers a Set
object which is a data type to hold unique elements, ie. it will remove any duplicates from the input, thus, new Set(string)
removes all duplicate characters from the string, thus, we do new Set('' + num)
to pass num
as a string, now that the set contains only unique characters, set.size
will return number of unique characters in the string.
A number will have no repeated characters if the number of digits is equal to number of unique characters we found earlier, there are many ways to find number of digits in number, we could also do num.toString().length
instead of ~~Math.log10(num) + 1
, the logarithm of a number to base 10 gives us a decimal value, we convert it to integer, this integer will be 1 less than the number of digits, so, we add 1 to get number of digits.
Thus, it returns true when the lengths are not equal, implying that there is repetition, and false otherwise.