简体   繁体   English

Javascript-在字符串中添加缺少的括号

[英]Javascript - Add missing parentheses in string

This is my code: 这是我的代码:

function pars(str) {
    var p = [str.split("(").length - 1, str.split(")").length - 1];

    if (p[0] > p[1]) {
        for (var i = 0; i < (p[0] - p[1]); i++) {
            str += ")";
        }
    }

    return str;
}

It adds parentheses in the end of the string if it's missing. 如果缺少,它将在字符串末尾添加括号。

Examples: 例子:

"((asd)s" -> "((asd)s)"
"(((ss)123" -> "(((ss)123))"

How can I make this work for beginning parentheses aswell? 我怎样才能使此功能也成为括号的开头呢?

Like: 喜欢:

"))" -> "(())"
")123))" -> "((()123))"

Here is a simple stack-based approach. 这是一个简单的基于堆栈的方法。 The full JSFiddle is below as well as list of confirmed test cases. 下面是完整的JSFiddle以及已确认的测试用例的列表。

function pars(s) {
    var missedOpen = 0, stack = new Array();
    for (i = 0; i < s.length; i++) {
        if (s[i] == '(') {
            stack.push(s[i]);
        } else if (s[i] == ')') {
            if (!stack.pop())
                missedOpen++;
        }
    }
    return Array(missedOpen + 1).join('(') + s + Array(stack.length + 1).join(')');
}

Confirmed Test cases: 确认的测试用例:

// Target: Expected
var cases = {
    '()': '()',
    ')(': '()()',
    '(': '()',
    ')': '()',
    'This)(is))a((test)': '((This)(is))a((test))',
    '(A)': '(A)',
    ')A(': '()A()'
};

See the complete JSFiddle is here . 看到完整的JSFiddle在这里

As noted by a comment, here's a version without the array at all. 正如评论所指出的,这是一个完全没有数组的版本。 This should be the most efficient method. 这应该是最有效的方法。 All the test cases passed. 所有测试用例都通过了。

function pars(s) {
    var missedOpen = 0, missedClosed = 0;
    for (i = 0; i < s.length; i++) {
        if (s[i] == '(') {
            missedClosed++;
        } else if (s[i] == ')') {
            if (missedClosed > 0)
                missedClosed--;
            else
                missedOpen++;
        }
    }
    return Array(missedOpen + 1).join('(') + s + Array(missedClosed + 1).join(')');
}

You need both the number of unmatched beginning parenthesis and the number of unmatched end parenthesis. 您既需要不匹配的开始括号的数量,也需要不匹配的结束括号的数量。 Here is a rough solution: 这是一个粗略的解决方案:

function pars(str) {
    var p = 0;
    var minp = 0;

    for (var i = 0; i < str.length; i++) {
        if (str[i] == "(") p++;
        if (str[i] == ")") {
            p--;
            if (p<minp) minp = p;
        }
    }
    for (i = 0; i > minp; i--) {
        str = "(" + str;
    }
    p = p - minp; // If we added any starting parenthesis, we need to end those as well.
    for (i = 0; i < p; i++) {
        str = str + ")";
    }

    return str;
}

This is an extremely dirty solution (which works in Firefox for the time being due to repeat function): 这是一个非常脏的解决方案(由于repeat功能,暂时无法在Firefox中使用):

function pars(str) {
    var t = str;
    var n;
    while ((n = t.replace(/\([^()]*\)/g, "")) != t) {
        t = n;
    }

    var open = t.match(/\)/g);
    var close = t.match(/\(/g);

    return "(".repeat(open.length) + str + ")".repeat(close.length);
}

Basically, it matches all pairs of () , then count the number of ( and ) , and append ) and ( accordingly. 基本上,它匹配所有()对,然后计算()的数量,并追加)(相应地。

A clean solution should use a counter to count the number of opening unmatched parentheses. 一个干净的解决方案应该使用一个计数器来计算不匹配括号的数量。 It will discard and count the number of unmatched ) . 它将丢弃并计算不匹配的数量) For the number of unmatched ( , do as per normal. It will be a one-pass solution, instead of multi-pass solution like the one above. 对于不匹配的数量( ,请按常规进行。这将是单程解决方案,而不是上述的多程解决方案。

This one seems to work: 这似乎可行:

 function pars(str){ var pars = [].reduce.call(str, function(acc, letter){ if(letter === '(') { acc.right++;} else if(letter === ')') { if(acc.right) {acc.right--;} else {acc.left++;}//no starting one } return acc; }, {left: 0, right: 0}), left = pars.left, right = pars.right; if(left) { str = new Array(left+1).join('(') + str;} if(right) { str += new Array(right+1).join(')');} return str } var str = ')))(((fdfd)fd)(' $("#out").html(str + " - " + pars(str)) 
 <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script> <div id="out"/> 

You can use a variation on the famous stack based bracket matching algorithm here. 您可以在此处使用著名的基于堆栈的括号匹配算法的变体。

The general idea is that you scan the code and push an opening parenthesis onto the stack when you see one, then when you see a closing one you pop the top value from the stack and continue. 通常的想法是,您扫描代码并在看到一个圆括号时将其插入到堆栈中,然后在看到一个圆括号时从堆栈中弹出最高值并继续。 This will ensure that you have the correct balance. 这样可以确保您拥有正确的余额。

(123())
// ( - push -> ['(']
// 1 - nothing
// 2 - nothing
// 3 - nothing
// ( - push -> ['(', '(']
// ) - pop -> ['(']
// ) - pop -> []

However, we want to bend the rules slightly. 但是,我们希望略微修改规则。

  • If we push a closing paren onto the stack, and the stack is empty: we need to add an opening paren to the start of the string 如果将结束括号推入堆栈,而堆栈为空:我们需要在字符串的开头添加开头括号
  • If we arrive at the end of the string and there are still open parens on the stack, then we need to close them. 如果我们到达字符串的末尾,并且堆栈上仍然有打开的paren,那么我们需要关闭它们。

So the code would look something like this: 因此代码看起来像这样:

function parse(str) {
  var stack = []
    out = str,
    idx = 0,
    chr = '';

  for(idx = 0; idx < str.length; idx++) {
    chr = str[idx];

    if(chr === '(') {
      stack.push(chr);
    }

    else if(chr === ')') {
      if(stack.length > 0) {
        stack.pop();
      } else {
        out = '(' + out;
      }
    }

  }

  for(idx = 0; idx < stack.length; idx++) {
    out = out + ')';
  }

  return out;
}

Bonus : Because of the iterative stack based nature of this algorithm, it will generally be faster than RegEx alternatives. 奖励 :由于此算法基于迭代堆栈的性质,因此通常比RegEx替代方法更快。

Just scan the string, counting parens. 只需扫描字符串,计数括号。 +1 for (, -1 for ). +1代表(,-1代表)。 If the number goes negative, you're missing a ( at the beginning. If, when you are finished, the number is positive, then that's how many )s you need to add at the end. 如果数字为负数,则表示开头缺少(。如果完成后,数字为正数,则表示末尾需要增加)。

var addmissingparens = function(s){
    var n = 0;
    Array.prototype.forEach.call(s, function(c){
        if(c === '('){
            n += 1;
        }
        if(c === ')'){
            if(n === 0){
                s = '(' + s;
            }else{
                n -= 1;
            }
        }
    });
    for(; n>0; n-=1){
        s += ')';
    }
    return s;
};

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM