4

我必须读入一个包含多个坐标的文件。该文件的结构如下:

X1/Y1,X2/Y2,X3/Y3,X4/Y4

其中 X 和 Y 是正整数。为了解决这个问题,我想使用一个正则表达式(我认为这通常是一个好主意,因为模式改变时重构最少)。

因此,我开发了以下正则表达式:

Regex r = new Regex(@^(?<Coor>(?<X>[0-9]+)/(?<Y>[0-9]+))(,(?<Coor>(?<X>[0-9]+)/(?<Y>[0-9]+)))*$");

但是,当我在数据上测试这个正则表达式时,例如:

1302/1425,1917/2010

正则表达式似乎只记得最后一个 X、Y 和 Coor 组。在这种情况下,Coor 是“12/17”,X 是“1917”,Y 是“2010”。有没有办法生成某种树。所以我找到了一个对象,它给了我所有的 Coor 表达式,在每个 Coor 下都有一个 X 和 Y 分量?

如果可能,我只想使用一个正则表达式,因为格式可能会更改为另一种。

4

4 回答 4

5

您可以使用string.Splitand轻松解决此问题,无需任何正则表达式int.Parse

var coords = s.Split(',')
    .Select(x => x.Split('/'))
    .Select(a => new {
        X = int.Parse(a[0]),
        Y = int.Parse(a[1])
    });

如果您想使用正则表达式来验证字符串,您可以这样做:

"^(?!,)(?:(?:^|,)[0-9]+/[0-9]+)*$"

如果您还想使用基于正则表达式的方法来提取数据,您可以首先使用上述正则表达式验证字符串,然后按如下方式添加数据:

var coords = Regex.Matches(s, "([0-9]+)/([0-9]+)")
    .Cast<Match>()
    .Select(match => new
    {
        X = int.Parse(match.Groups[1].Value),
        Y = int.Parse(match.Groups[2].Value)
    });

如果您真的想使用单个正则表达式同时执行验证和数据提取,您可以使用两个捕获组并在Captures每个组的属性中查找结果。这是您可以使用单个正则表达式执行验证和数据提取的一种方法:

List<Group> groups =
    Regex.Matches(s, "^(?!,)(?:(?:^|,)([0-9]+)/([0-9]+))*$")
         .Cast<Match>().First()
         .Groups.Cast<Group>().Skip(1)
         .ToList();

var coords = Enumerable.Range(0, groups[0].Captures.Count)
    .Select(i => new
    {
        X = int.Parse(groups[0].Captures[i]),
        Y = int.Parse(groups[1].Captures[i])
    });

但是,您可能需要考虑与基于解决方案相比,此解决方案的复杂性是否值得string.Split

于 2010-10-13T20:22:31.450 回答
3

没有理由对这种简单的格式使用正则表达式。

只需拆分字符串并使用纯字符串操作来获取坐标:

var coordinates =
  fileContent.Split(',').Select(s => {
    int pos = s.IndexOf("/");
    return new {
      X = s.Substring(0, pos),
      Y = s.Substring(pos + 1)
    };
  });

如果文件格式变得更加复杂,您可以将其重构为使用正则表达式。在那之前,像这样的简单代码更容易维护。

于 2010-10-13T20:32:28.680 回答
2

如果您使用“匹配”而不是“匹配”命令,您可能会得到想要的结果。另外,您不能将正则表达式缩短为:

Regex(@"((?<Coor>(?<X>[0-9]+)/(?<Y>[0-9]+))|,)*");
于 2010-10-13T20:23:22.553 回答
1

我认为您的第一个问题是您的正则表达式有缺陷,锚点正在脱离匹配。这是我想出的一个:(只是这里显示的正则表达式,没有代码)

(?<Coor>(?<X>[0-9]+)/(?<Y>[0-9]+))

一个 Mystagogue 也可以,但会在逗号上生成“空白”匹配项(对我而言)。

于 2010-10-13T20:27:42.963 回答