Regex用于检查指南针方向

本文关键字:方向 指南针 检查 用于 Regex | 更新日期: 2023-09-27 18:19:58

我希望匹配可能出现在街道或位置前缀或后缀中的8个主要方向,例如:

  • NMain
  • I-22
  • 格罗弗大街124号东南

这很容易使用蛮力匹配列表进行编码,并在每个街道地址的每个匹配可能性中循环,一次与字符串锚的开头匹配,一次匹配字符串锚的结尾。如果你想看的话,我直率的起点显示在更远的地方。

我的问题是,是否有人对紧凑、快速执行的模式有一些聪明的想法来完成同样的事情。你可以假设:

  • 复合方向始终从北/南分量开始。所以我需要匹配东南,但不是东南
  • 模式应该而不是匹配[direction]-ern单词,如"Northern"或"Southwestern"
  • 匹配将始终在字符串的最开始或最末尾

我正在使用C#,但我只是在寻找一种模式,所以我不强调语言。对于我或未来的读者来说,/s(outh)?/@"s(outh)?"一样好。

SO强调真实的问题,所以仅供参考。我正在分析几十万个讨厌的、未经验证的用户键入的地址字符串。我想检查"街道"字段(由邮政信箱、街道、公寓和直接的无效垃圾组成的自由形式的混乱)的开始或结束是否以指南针方向开始或结束。我试图解构这些自由形式的字符串,以找到类似的地址,这些地址可能是偶然或有意的变化和混淆。

我的直率尝试

核心模式:/n(orth)?|e(ast)?|s(outh)?|w(est)?|n(orth's*east|e|orth's*west|w)|s(outh's*east|e|outh's*west|w)/

在一个函数中:

public static Tuple<Match, Match> MatchDirection(String value) {
    string patternBase = @"n(orth)?|e(ast)?|s(outh)?|w(est)?|n(orth's*east|e|orth's*west|w)|s(outh's*east|e|outh's*west|w)";
    Match[] matches = new Match[2];
    string[] compassPatterns = new[] { @"^(" + patternBase + @")'b", @"'b(" + patternBase + @")$" };
    for (int i = 0; i < 2; i++) { matches[i] = Regex.Match(value, compassPatterns[i], RegexOptions.IgnoreCase); }
    return new Tuple<Match, Match>(matches[0], matches[1]);
}

在使用中,sourceDt是一个包含所有地址的表:

var parseQuery = sourceDt.AsEnumerable()
    .Select((DataRow row) => {
        string addr = ((string)row["ADDR_STREET"]).Trim();
        Tuple<Match, Match> dirMatches = AddressParser.MatchDirection(addr);
        return new string[] { addr, dirMatches.Item1.Value, dirMatches.Item2.Value };
    })

Regex用于检查指南针方向

编辑:事实上,这可能是一个错误的答案——所以保留它只是为了让人们不会提出同样的建议——弄清楚"东南"的标记化本身就是一项任务。此外,我仍然怀疑RegExp是否也会非常有用。

原答覆:不要。。。您最初的RegExp尝试已经不可读。

从标记化字符串中查找每个单词的字典("蛮力方法")已经为您提供了长度上的线性时间和每个单词的恒定时间。而且它很容易用新词进行自定义。

(^[nesw][^n's]*)|([nesw][^n's]*$)

因此,这将匹配一条线:

  • 以一个单词开头或结尾:
    • 从基本方向开始
    • 没有其他n(去掉"-en")

Perl/PCRE兼容表达式:

(?xi)
(^)?
'b
(?:
  n(?:orth)?
  (?:'s* (?: e(?:ast)? | w(?:est)? ))?
|
  s(?:outh)?
  (?:'s* (?: e(?:ast)? | w(?:est)? ))?
|
  e(?:ast)?
|
  w(?:est)?
)
'b
(?(1)|$)

我认为C#支持这里使用的所有功能。