通过递归保留原始参数(首选Javascript)

时间:2016-12-20 22:19:59

标签: javascript recursion

我正在使用字母数字排序进行正则表达式解析来比较两个参数。首先,我应该忽略前导零以进行令牌比较。但是如果所有令牌都相等,则带有前导零的标记较小 所以我做一个像/(\ D | [1-9])/这样的正则表达式并递归解析(比较第一个令牌,如果相等,则通过regex.exec(arg1,arg2)传回新的字符串减去前导相等的令牌

但是如果一切都是平等的,我想用regex /(\ D | 0 * \ d)/再次对整个事情进行处理以捕获前导零。我试着通过返回一个公式来做到这一点。原来变成了: 函数(arg1,arg2,orig1,orig2);

然后我返回

函数比较(arg1new,arg2new,arg1,arg2)

但是在循环迭代中会发生的事情是,arg1new变为arg1,它会在orig1点返回...所以我丢失了原始的函数参数,而只是一个循环后面的相同参数。

有没有办法通过所有递归来保存原始参数...并且仅在结束时调用?

示例:

function alphanumericLess(s1, s2, orig1, orig2) {
    console.log(s1,s2);
    if(s1.length<1 && s2.length>=1){ //if 1st string is shorter
        return true;
    }
    var regex = /(\D|[1-9])(.*)/;
    var leadS1 = regex.exec(s1); //parse string1 ignoring leading zeroes
    var leadS2 = regex.exec(s2); //parse string2 ignoring leading zeroes

    if(leadS1[1]==leadS2[1]){ 
        console.log('if equals loop');
        return alphanumericLess(leadS1[2],leadS2[2],s1,s2);

    } else if(leadS1[1]<leadS2[1]){ 
        return true;
    }  else return false; //here is where I want to then re-run the recursion with /(\D|0*\d)/ to capture the leading zeroes comparison scenario

}

2 个答案:

答案 0 :(得分:0)

一些显示示例的伪代码:

function keep (a,b) {
  if (a == b) {
    return b;
  }
  else {
    return keep(a + 1, b);
  }
}
keep(1, 5);

B一直向上传递,然后再一次向下......

答案 1 :(得分:0)

您可以通过在现有函数中创建一个本地函数来解决这个问题,这些函数将被递归调用而不是现有函数。然后你可以用两种不同的方式调用那个局部函数来启动递归两次。

您当前的代码也存在一些问题:

  • 比较函数应该更好地符合sort回调所需的签名,即当第一个参数应该在第二个参数之前排序时它应该返回一个负数,当它们相等时它应该返回0,如果第一个应该在第二个之后排序,则为1。
  • 正则表达式只匹配一个字符,但对于自然排序,您应该将数字组与数字组进行比较,例如在12AB' and 123AB`中,比较应该在12和123之间,而不是&# 39; A&#39;和3.
  • 开始时的结束条件尚未完成。当第二个字符串为空时,您还应该处理这种情况。
  • 如果传递以零结尾的字符串,代码将失败。在这种情况下,只剩下那个零时,正则表达式不会产生结果。如果你预处理字符串以删除前导零(包括最后出现的那些),那将会容易得多。然后在第二个实例中,您可以重新启动递归而不进行此类替换,但在两种情况下都使用匹配所有字符(包括0)的正则表达式。

这是一个解决方案:

&#13;
&#13;
function alphanumericLess(s1, s2) {
    // Use a local function for the recursion, so it can be called twice
    function recurse(s1, s2) {
        if (!s1.length || !s2.length) { // test ALL end conditions
            // Don't return a boolean, but a numerical value
            return s1.length - s2.length; 
        }
        // Match multiple characters/digits as one part, deal with the 0 exclusion 
        // before calling the recurse function:
        var regex = /(\D+|\d+)(.*)/;
        var leadS1 = regex.exec(s1);
        var leadS2 = regex.exec(s2);
        if (leadS1[1] === leadS2[1]) { // Use strict comparison where possible
            return recurse(leadS1[2], leadS2[2]);
        } // After an if-return, else is not needed
        // As parts can have different lengths, use appropriate comparison method, 
        // and return a number that represents the comparison result
        if (isNaN(leadS1[1]) || isNaN(leadS2[1])) {
            return leadS1[1].localeCompare(leadS2[1]);
        }
        // In the numerical case, if equal, give precedence to the 
        // longest representation (zero-padded):
        return +leadS1[1] - +leadS2[1] || leadS2[1].length - leadS1[1].length;
    }
    // First call above function with leading zeroes removed.
    // If that yields equality, call it again without such removal:
    return recurse(s1.replace(/\b0+/g, ''), s2.replace(/\b0+/g, ''))
        || recurse(s1, s2);
}

console.log(alphanumericLess('012Ab3X0', '12Ab3X0')); // negative => order is correct
console.log(alphanumericLess('Ab30X0', 'Ab3X0')); // positive => order is reversed
console.log(alphanumericLess('Ab30X0', 'Ab30X0')); // zero => equal
// Use in sort: output is [ "001A", "1A", "2A", "B0999", "B0999X", "B999X" ]
console.log(['B999X', '1A', 'B0999', '001A', 'B0999X', '2A'].sort(alphanumericLess));
&#13;
.as-console-wrapper { max-height: 100% !important; top: 0; }
&#13;
&#13;
&#13;

说明

在第一次扫描中忽略前导零的代码不在递归之外:它是通过一次删除那些前导零来完成的。这样两个扫描的递归函数是相同的,只是参数不同。

在递归函数的每次调用中执行正则表达式效率不高。在进入递归之前对字符串进行拆分会更有效。当然,非递归函数会更有效。

最后,自然排序通常也不区分大小写。您可能也希望将该逻辑放在您的函数中。