对于具有奇数和偶数长度的数字,如何最好地确定最严格数字的左边的数字?

时间:2019-02-03 06:53:40

标签: javascript algorithm luhn

我正在编写代码,以检查一定数量的信用卡号输入是否有效。我写过:

function validCreditCard(value) {
    // accept only digits, dashes or spaces
    if (value.trim().length <= 1) return 'Value entered must be greater than 1';
    if (/[^0-9\s]+/.test(value)) return false;

    // Remove all white spaces
    value = value.replace(/\D/g, '');

    for (var i = 0; i < value.length; i++) {
    // code goes here
    // Loop through the string from the rightmost moving left and double the value of every second digit.
}

由于字符串的长度可以是偶数或奇数,因此我一直试图绕过如何从最右边向左移动字符串并使第二个数字的值翻倍。例如,对于长度为16(偶数)的输入,左边的第一个数字将是第15个位置(索引14),对于长度为11的奇数输入,左边的第一个数字将是第10个位置(索引9)。我编写的程序在两种情况下均不起作用,现在我想编写一种程序来解决这两种情况。在没有创建两个单独的检查以查看输入长度是奇数还是偶数的情况下,如何最好地实现这一目标?

P.S:某些在线实施在两种情况下也不起作用。

2 个答案:

答案 0 :(得分:1)

要真正知道“右边第二个数字”中的哪个,您实际上并不需要从头到尾进行迭代。也可以从左到右完成。要知道某个数字是否是这样的“第二”数字,请将其奇/偶奇偶校验与输入长度的奇偶校验进行比较。

像这样:

var parity = value.length % 2;
for (var i = 0; i < value.length; i++) {
    if (i % 2 === parity) {
        // "Special" treatment comes here
    } else {
        // "Normal" treatment comes here
    }
}

但是如果输入的长度为奇数,也可以在输入之前加上零,以使其具有偶数的长度:

if (value.length % 2) value = '0' + value;
for (var i = 0; i < value.length; i++) {
    if (i % 2 === 0) {
        // "Special" treatment comes here
    } else {
        // "Normal" treatment comes here
    }
}

您要实现的称为Luhn algorithm。因此,使用长度的奇偶校验,它看起来可能像这样:

function validCreditCard(value) {
    // Accept only digits, dashes or spaces
    if (/[^0-9\s-]+/.test(value)) return false;
    // Get the digits only
    value = value.replace(/\D/g, "");
    // Need at least one digit
    if (!value.length) return false;
    var parity = value.length % 2;
    var sum = 0;
    for (var i = 0; i < value.length; i++) {
        sum += i % 2 === parity
            ? (value[i]*2) % 10 + (value[i] > '4') // Double, and add one if double > 9
            : +value[i]; // Normal case
    }
    return sum%10 === 0;
}

console.log(validCreditCard("4024007112651582"));

说明:

在循环中,我用conditional ternary operator-if...else...替换了... ? ... : ...构造-在两种情况下都需要为变量分配值时,这很实用(在我们的情况下为sum)。

对于“普通”数字,sum必须与数字的值(+value[i])一起增加。加一元运算符会将字符转换为数字值-因此+'1'变为1。

对于“特殊”数字,必须将sum增加一个数字值(value[i]*2)的两倍。请注意,由于乘法运算,从字符串到整数的转换是自动发生的。

这时,我们需要处理此双精度值由两位数字组成的情况。例如:8 * 2 =16。在这种情况下,结果数字不应为6,而应为7。因此,我们添加(value[i] > '4')。那确实是布尔表达式(falsetrue):当双精度数有两位数字时,这是正确的。通过添加布尔值,可以将其分别强制为0或1-正是我们所需要的。

答案 1 :(得分:0)

  

从最右边向左移动字符串,然后将   每两位数字的值

您可以使用.reverse().map()和余数运算符%

let arr = [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16];

var res = [...arr].reverse().map((a, i) => i % 2 ? a * 2 : a).reverse();

console.log(res);