0

基本上我需要计算一个字符串中的 agrupations 总数,这是为了显示一些信息,例如在正则表达式应用程序中打开的子标记表达式的总数的建议。

然后我需要计算关闭“()”的总数,而不是“(”的总数和“)”的总数分开。

例如在这个字符串中:

Hello (world)

预期的结果是:1 关闭

这里:

Hello (world) ((how are (you)?

预期的结果是:2 个关闭,2 个打开

和这里:

Hello ) ( World?

预期的结果是:2 打开

请问可以给我一些想法,哪些可以改进计算它们的方法?

我得到了“(”和“)”字符的总数,现在我不知道该怎么办。

更新:

我用这个字符串示例进行测试:

(((X)))

但是我有 4 个未关闭,只有 1 个关闭,我正在使用以下代码:

Public Function Replace_All_Characters_Except(ByVal str As String, _
                                              ByVal chars As Char(), _
                                              replaceWith As Char) As String

    Dim temp_str As String = String.Empty

    For Each c As Char In str
        For Each cc As Char In chars
            If c = cc Then temp_str &= cc
        Next cc
    Next c

    Return temp_str

End Function

    Dim Total_Parentheses As String = Replace_All_Characters_Except(TextBox_RegEx.Text, {"(", ")"}, String.Empty)
    Dim Total_Unagrupated As Integer = Total_Parentheses.Replace("()", String.Empty).Length
    Dim Total_Agrupated As Integer = (Total_Parentheses.Length - Total_Unagrupated) \ 2

    MsgBox(Total_Parentheses)
    MsgBox(Total_Unagrupated)
    MsgBox(Total_Agrupated)
4

3 回答 3

6

我会在这里使用堆栈

Stack<char> stack = new Stack<char>();
string input = @"Hello (world) ((how are (you)?";
//string input = "Hello ) ( World?";

int closed = 0;
int opened = 0;

foreach (var ch in input)
{
    if (ch == '(')
        stack.Push('#');
    else if (ch == ')')
    {
        if (stack.Count == 0)
            opened++;
        else
        {
            closed++;
            stack.Pop();
        }
    }
}

opened += stack.Count;

Console.WriteLine("Opened:{0} Closed:{1}", opened, closed);

编辑

    Dim stack As New Stack(Of Char)
    Dim input As String = "Hello (world) ((how are (you)?"
    'Dim input As String = "Hello ) ( World?"

    Dim opened As Integer = 0
    Dim closed As Integer = 0

    For Each ch As Char In input
        If ch = "(" Then
            stack.Push("#")
        ElseIf ch = ")" Then
            If stack.Count = 0 Then
                opened = opened + 1
            Else
                closed = closed + 1
                stack.Pop()
            End If
        End If
    Next

    opened = opened + stack.Count

    Console.WriteLine("Opened:{0} Closed:{1}", opened, closed)
于 2013-09-09T16:54:07.737 回答
1

一种方法是从字符串中删除除括号外的所有字符。然后,迭代地从字符串中删除闭合对,直到没有剩余。其余字符不匹配。伪代码:

string sanitize(string s, List<string> valid_characters){
    string sanitized = "";
    for (char c in s){
        if (valid_characters.contains(c)){
            sanitized.append(c);
        }
    }
    return sanitized;
}

string s = ")Hello((World)())(";

s = sanitize(s, {"(", ")"});
int total_parens = s.length;
while(s.contains("()")){
    s = s.replace("()", "");
}
int unmatched_parens = s.length;
int matched_parens = total_parens - unmatched_parens;
int matched_pairs = matched_parens/2;

在这里,")Hello((World)())(" 被清理为 ")(()())(",并且total_parens是 8。它减少到 ")(())("、")()( ",最后是 ")(".unmatched_parens是 2,matched_pairs是 3。

于 2013-09-09T16:47:40.787 回答
0

如果您想知道问题中描述的“打开的情况”的数量,我能想到的最好方法是循环(通过函数调用):

Private Function isOpen(inputString As String) As Integer()

    Dim outArray(2) As Integer
    Dim outOpen As Integer = 0
    Dim outClose As Integer = 0


    Dim openCount As Integer = 0
    Dim closeCount As Integer = 0
    For Each curChar As Char In inputString
        If (curChar = ")") Then
            closeCount = closeCount + 1
            If (openCount > 0) Then
                outClose = outClose + 1
                openCount = openCount - 1
                closeCount = closeCount - 1
            ElseIf (openCount = 0) Then
                outOpen = outOpen + 1
                openCount = 0
                closeCount = 0
            End If
        ElseIf (curChar = "(") Then
            openCount = openCount + 1
        End If
    Next

    If (openCount <> closeCount) Then
        outOpen = outOpen + Math.Abs(openCount - closeCount)
    End If

    Return New Integer() {outOpen, outClose}
End Function

通过以下方式调用:

Dim temp() As Integer = isOpen(inputString)
Dim totOpened As Integer = temp(0)
Dim totClosed As Integer = temp(1)
于 2013-09-09T16:36:42.847 回答