用于检查罗盘方向的正则表达式

时间:2012-01-11 21:08:07

标签: c# regex

我希望匹配街道或位置前缀或后缀中显示的8个主要方向,例如:

  • N 主要
  • I-22
  • 124 Grover Ave SE

这很容易使用强力匹配列表进行编码,并循环遍历每个街道地址的每个匹配可能性,使用字符串开始锚点匹配一次,使用字符串结束锚点匹配一次。如果你想看到它,我的直接起点会显示得更远。

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

  • 复合方向始终以北/南组件开头。所以我需要匹配东南而不是东南
  • 该模式匹配[方向] -ern字样,如“Northern”或“Southwestern”
  • 匹配将始终位于字符串的开头或结尾。

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

SO强调真正的问题,所以仅供参考。我正在解析几十万个讨厌的,未经验证的用户类型地址字符串。我想检查“街道”字段的开头或结尾(PO框,街道,公寓和直线无效垃圾的自由形式混乱)是否以罗盘方向开始或结束。我正在尝试解构这些自由格式字符串,以找到类似的地址,这些地址可能是偶然或有意的变化和混淆。

我的直率尝试

核心模式:/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 };
    })

3 个答案:

答案 0 :(得分:2)

编辑:实际上这可能是错误的答案 - 所以保持它只是让人们不建议同样的事情 - 找出“东南”的标记化本身就是一项任务。此外,我仍然怀疑RegExp是否也非常有用。

原始答案: 不要......您的初始RegExp尝试已经不可读。

字典从标记化字符串中查找您想要的每个单词(“强力方法”)已经为您提供了线性时间长度和每个单词的恒定时间。用新单词定制很容易。

答案 1 :(得分:0)

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

所以这将匹配一行:

  • 以一个词开头或结尾:
    • 以主要方向开始
    • 否则没有n(摆脱“-ern”)

答案 2 :(得分:0)

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#支持此处使用的所有功能。