我有一个Token类的以下字符列表:
3 ( 16 ) 23 ( 24 ( 40 ) 50 ( 66 ) 76 ) 83 ( 88 ( 104 ) 127 )
我的要求是在这个列表中找到括号对。在列表中,括号对分别为:3,16;24日,40;50, 66;23日,76;88104;83127 .
我正在尝试用以下方法做这件事:
public static Dictionary<int,int> GetPair(List<Token> data)
{
List<Token> token = data;
var pair = new Dictionary<int, int>();
int startIndex = -1;
int currentPosition = -1;
int finalIndex = -1;
foreach (var item in token)
{
if (item.TokenValue == "(" && (currentPosition == -1 || currentPosition>startIndex) )
{
startIndex = item.TokenID;
currentPosition = startIndex;
}
if (item.TokenValue == ")")
{
finalIndex = item.TokenID;
currentPosition = finalIndex;
pair.Add(startIndex, finalIndex);
}
}
return pair;
}
public class Token
{
public int TokenID { get; set; }
public string TokenValue { get; set; }
}
我被困在寻找"23("的位置,因为在列表中有另一个开括号,它用"24("代替了它。请帮我修复这里的逻辑??
我还没有测试过,但这应该可以解决问题:
public static Dictionary<int,int> GetPair(List<Token> data)
{
var pair = new Dictionary<int, int>();
var stack = new Stack<Token>();
foreach (var item in token)
{
if (item.TokenValue == "(")
{
stack.Push(item);
continue;
}
if (item.TokenValue == ")")
{
var starting = stack.Pop();
pair.Add(starting.TokenId, item.TokenId);
}
}
return pair;
}
这是一个经典的面试问题,你可以用Stack
来解决:
public static Dictionary<int,int> GetPair(List<Token> data)
{
Stack<Token> stacken = new Stack<Token>();
var pair = new Dictionary<int, int>();
Token temp = new Token();
foreach (char A in data)
{
if (item.TokenValue == "(" )
{
stacken.Push(A);
}
if (item.TokenValue == ")" )
{
if (stacken.Last() == '(')
{
temp = stacken.Pop();
pair.Add(temp.TokenID,item.TokenID)
}
else
{
stacken.Push(A);
}
}
}
return pair;
}
您也可以使用正则表达式。可能不会像Vera rind溶液那么快。
string s = "3 ( 16 ) 23 ( 24 ( 40 ) 50 ( 66 ) 76 ) 83 ( 88 ( 104 ) 127 )".Replace(" ", string.Empty);
Regex regex = new Regex(@"(([0-9]+)([0-9]+))");
Regex regexNumber = new Regex(@"[0-9]+");
Match match = regex.Match(s);
List<Tuple<int, int>> pairs = new List<Tuple<int, int>>();
while (match.Success)
{
var pairNumber = regexNumber.Matches(match.Value);
if (pairNumber.Count == 2)
{
var newPair = new Tuple<int, int>(int.Parse(pairNumber[0].Value), int.Parse(pairNumber[1].Value));
pairs.Add(newPair);
}
// remove last parse
s = s.Replace(match.Value, string.Empty);
match = regex.Match(s);
}
EDIT
多亏了Vera rind的建议,我也写了解决方案,为每一个(嵌套级别)与。NET regex风味,正则表达式:
(?<first>d+)(?=s(s(?<second>d+)s))|(?<first>d+)s(?=(s(?:(?:[^()]|(?<Open>()|(?<Content-Open>)))+(?(Open)(?!))s(?<second>d+)))
演示捕获first
和second
组中的成对值。Regex直接匹配对的第一个值,第二个值由正向前看的组捕获。这不是最有效的方法,只是更容易在正则表达式测试器中验证是否匹配正确。
在其他正则表达式口味(据我所知)没有这样优雅的方式来匹配平衡的可修复结构,所以对于两级括号,这个解决方案仍然有效。静态解决方案在这种情况下更好,但如果整个数据是相同的格式(空格和最大两层括号深度),也可以使用regex:
(d+)s(s(d+)s)|(d+)(?=s(s(?:d+s(sd+s)s)+(d+))
演示 地点:
-
(d+)s(s(d+)s)
-匹配简单情况:与以下数字匹配括号中的数字:n1 (n2)
,值捕获在组1 &2, -
(d+)(?=s(s(?:d+s(sd+s)s)+(d+))
-匹配号码以下嵌套括号中的最后一个单独数字:n1 ( x1 (x2) y1 (y2) n2 )
,值在第3组&4、