我希望匹配街道或位置前缀或后缀中显示的8个主要方向,例如:
这很容易使用强力匹配列表进行编码,并循环遍历每个街道地址的每个匹配可能性,使用字符串开始锚点匹配一次,使用字符串结束锚点匹配一次。如果你想看到它,我的直接起点会显示得更远。
我的问题是否有人对紧凑,快速执行的模式有一些聪明的想法来完成同样的事情。你可以假设:
我正在使用C#,但我只是在寻找一种模式,所以我不是在强调这种语言。对于我或未来的读者来说,/s(outh)?/
与@"s(outh)?"
一样好。
我的直率尝试
核心模式:/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 };
})
答案 0 :(得分:2)
编辑:实际上这可能是错误的答案 - 所以保持它只是让人们不建议同样的事情 - 找出“东南”的标记化本身就是一项任务。此外,我仍然怀疑RegExp是否也非常有用。
原始答案: 不要......您的初始RegExp尝试已经不可读。
字典从标记化字符串中查找您想要的每个单词(“强力方法”)已经为您提供了线性时间长度和每个单词的恒定时间。用新单词定制很容易。
答案 1 :(得分:0)
(^[nesw][^n\s]*)|([nesw][^n\s]*$)
所以这将匹配一行:
答案 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#支持此处使用的所有功能。