检查一个数字是否有重复的数字

4

如何检查数字是否在一个数字中出现了多次(任意位置)?


示例输入数字:

1, 10, 11, 1010, 1981

输出应告诉哪个数字有重复的数字:

false, false, true, true, true

将在jsperf页面上给出的所有好答案发布出来


7个回答

5

我认为最快的方法是使用正则表达式测试。您可以使用它快速地得到一个关于是否存在重复的真或假,并且它足够紧凑,可以在条件运算符中使用。这里有一个适用于数字和数字字符串的示例。

function hasRepeatingdigits(N) {
  return (/([0-9]).*?\1/).test(N)
}  

console.log(
[1, 10, 11, 1010, 1981, 12345678901, 123456789].map(hasRepeatingdigits)
)

以下是关于正则表达式如何工作的详细说明:
[0-9]创建一个由数字0到9组成的字符列表,用于匹配。
• 添加括号([0-9])将此列表定义为第一个捕获组。如果您只需要搜索一个字符而不需要正则表达式执行后续操作,则不需要这些括号。(即:在字符串中查找字符0到9的第一个索引或在RegExp测试中查找true时,只需使用/[0-9]/).可以匹配除行终止符之外的任何单个字符。添加惰性量词*?,可匹配0到无限次数,尽可能少地匹配。
\1匹配最近由第一个捕获组匹配的相同文本。
总结一下:/([0-9]).*?\1/是一个正则表达式,在迭代字符串时查找每个0到9的字符,并在第一次匹配当前在第一个捕获组中的字符时返回匹配项。
在字符串'123432'中,这个RexExp会返回完整的匹配项:'2343',并在捕获组1:'2'中。
RegExp.prototype.test()使用提供的RegExp搜索字符串,如果RegExp返回一个匹配,则返回true,否则返回false。这很容易被修改,以便使用/([A-Za-z]).*?\1/).test(N)查找重复字母字符。
除了非常有用的MDN区域RegExp之外,我强烈建议那些想要更加熟悉它们的人去查看这个RegularExpressions101工具。

确实是最快的!谢谢!请查看我的问题以获取jsperf。 - vsync
你能否友好地解释一下这个正则表达式,让那些不知道它如何工作的人理解吗? - vsync
1
刚刚在答案中添加了一个详细说明。 - Isaac B

2

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))


1
你可以使用 Array#indexOfArray#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)));


1

使用Array.prototype.map()String.prototype.match()函数的简短解决方案:

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]));


1

    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)));


1
这个方法首先将数字转换为字符串:N = N + '',然后检查split()的结果,它是一个基于分隔符将字符串压缩成较小部分的字符串函数。
例如,如果我用"b"拆分"aba",我将得到包含["a", "a"]的数组。如你所见,如果有一个"b"出现,则返回的数组长度为2。如果有更多,则超过2。这就是我在解决方案中使用的方法。
作为奖励,它适用于其他类型的数据,甚至包括nullundefined。;)

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));
});


不错!我会编辑它使代码更短。将其添加到测试页面中(链接在我的问题中)。 - vsync
我在循环的初始化部分添加了 +=,使其更加简短。 - dodov
1
你甚至可以通过删除“return false;”来缩短代码。 - vsync
是的,但在问题中,您要求输出为“true”或“false”。 - dodov
1
是的,但在实际应用中,没有必要返回“false”,只是这么说。 - vsync

1

const isRepeated = (num) => new Set('' + num).size != ~~Math.log10(num) + 1;

[1, 10, 11, 1010, 1981].forEach(n => console.log(n, isRepeated(n)));

JS提供了一个Set对象,这是一种用于保存唯一元素的数据类型,即它将从输入中删除任何重复项,因此,new Set(string) 会从字符串中删除所有重复字符,因此,我们使用new Set('' + num) 将num作为字符串传递进去,现在该集合仅包含唯一的字符,set.size将返回字符串中唯一字符的数量。
如果数字的位数等于我们之前找到的唯一字符数,则该数字不会有重复的字符,可以通过多种方式查找数字中的位数,我们也可以使用num.toString().length而不是~~Math.log10(num) + 1,数的以10为底的对数给出一个小数值,我们将其转换为整数,该整数将比数字的位数小1,因此,我们加1来获取位数。
因此,当长度不相等时,它返回true,表示存在重复项,否则返回false。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接