正则表达式与字典键匹配 [英] Regex match with dictionary key

查看:487
本文介绍了正则表达式与字典键匹配的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在我解释之前,这是我的C#代码:



Before I explain, here is my C# code:

static Dictionary<string, string> phenom = new Dictionary<string, string>
{
    {"-", "Light"},
    {"\\+", "Heavy"},
    {"\bVC\b","In the Vicinity"},
    // descriptor
    {"MI","Shallow"},
    {"PR","Partial"},
    {"BC","Patches"},
    {"DR","Low Drifting"},
    {"BL","Blowing"},
    {"SH","Showers"},
    {"TS","Thunderstorm"},
    {"FZ","Freezing"},
    // precipitation
    {"DZ","Drizzle"},
    {"RA","Rain"},
    {"SN","Snow"},
    {"SG","Snow Grains"},
    {"IC","Ice Crystals"},
    {"PL","Ice Pellets"},
    {"GR","Hail"},
    {"GS","Small Hail/Snow Pellets"},
    {"UP","Uknown Precipitation"},
    // obscuration
    {"BR","Mist"},
    {"FG","Fog"},
    {"FU","Smoke"},
    {"VA","Volcanic Ash"},
    {"DU","Widespread Dust"},
    {"SA","Sand"},
    {"HZ","Haze"},
    {"PY","Spray"},
    // other
    {"PO","Well-Developed Dust/Sand Whirls"},
    {"SQ","Squalls"},
    {"FC","Funnel Cloud Tornado Waterspout"},
    {"SS","Sandstorm"},
    {"DS","Duststorm"}
};

public static string Process(String metar)
{
    metar = Regex.Replace(metar, "(?<=A[0-9]{4}).*", "");
    StringBuilder _string = new StringBuilder();

    var results = from result in phenom
                  where Regex.Match(metar, result.Key, RegexOptions.Singleline).Success
                  select result;

    foreach (var result in results)
    {
        if (result.Key == "DZ" || result.Key == "RA" || result.Key == "SN" || result.Key == "SG" || result.Key == "PL")
        {
            switch (result.Key)
            {
                case "+":
                    _string.Append("Heavy ");
                    break;
                case "-":
                    _string.Append("Light");
                    break;
                case "VC":
                    _string.Append("In the Vicinity ");
                    break;
                default:
                    break;
            }
        }

        _string.AppendFormat("{0} ", result.Value);
    }

    return _string.ToString();
}





基本上,此代码解析机场METAR天气报告中的天气现象。以下列METAR为例:



KAMA 230623Z AUTO 05016KT 7SM + TSRAGR FEW070 BKN090 OVC110 16/14 A3001 RMK AO2 PK WND 06026/0601 LTG DSNT E -SW RAB04 TSB02E17 P0005 T01560144



注意+ TSRAGR ......这是我想要关注的部分。我目前的代码工作得很好......但并不接近我真正想要的。它吐出这个:重雷暴雨冰。



实际解码略有不同。参考本手册(见第5页)。



强度指标(+和 - )总是在第一次降水之前出现。在上面的METAR中,它将是RA。因此,理想情况下应该吐出雷雨大雨。但事实并非如此。还有一些时候这种现象并不那么激烈......有时它可能只是-RA,在这种情况下应该只返回小雨。



另外注意,正如我引用的手册所说,强度标识符没有用IC,GR,GS或UP降水类型编码,这解释了我在追加强度之前检查键值的尝试,但是失败了。



如果有人能指出我如何在正确的位置附加强度标识符的正确方向,我会非常感激。


TL; DR ...基本上,我有一些代码逻辑来决定在字典列表中的特定项目之前放置前缀的位置。



Basically, this code parses the weather phenomenons in an airport METAR weather report. Take the following METAR for example:

KAMA 230623Z AUTO 05016KT 7SM +TSRAGR FEW070 BKN090 OVC110 16/14 A3001 RMK AO2 PK WND 06026/0601 LTG DSNT E-SW RAB04 TSB02E17 P0005 T01560144

Notice the +TSRAGR...this is the portion I want to focus on. The code I currently have works fine...but not close to what I actually want. It spits out this: "Heavy Thunderstorm Rain Hail".

The actual decoding differs slightly. Referenced from this manual (see the 5th page).

The intensity indicators (+ and -) always come before the first precipitation. In the above METAR, it would be RA. So, ideally it should spit out "Thunderstorm Heavy Rain Hail", instead. However, it is not. There are other times when the phenomena is not as intense...sometimes it may only be -RA, in which case should only return "Light Rain".

Also to note, as the manual I referenced says, the intensity identifiers are not coded with the IC, GR, GS or UP precipitation types, which explains my attempt at checking the key value before appending the intensity, but failed.

If someone could point me in the right direction on how to append the intensity identifiers in the right location, I'd much appreciate it.

TL;DR...basically, I some code logic to decide where to put prefixes before specific items from a dictionary list.

推荐答案

我认为这个解决方案可能有用。

不确定我是否理解可能发生的所有变化。



示例字符串

I think this solution might work.
Not certain I have understood all the variations that can occur.

Example string
string metar = "KAMA 230623Z AUTO 05016KT 7SM +TSRAGR FEW070 BKN090 OVC110 16/14 A3001 RMK AO2 PK WND 06026/0601 LTG DSNT E-SW RAB04 TSB02E17 P0005 T01560144";





带有组名的正则表达式。

如果我正确理解规范,则现在的天气组是由

可选强度

强制性DESCRIPTOR

一组或多组降水,OBSCURATION或其他。





Regular expression with group names.
If I understood the spec correctly, the Present Weather group is built up by
optional INTENSITY
mandatory DESCRIPTOR
one or more groups of either PRECIPITATION, OBSCURATION or OTHER.

Regex MetarExpression = new Regex(@"\s(?<intensity>[\+\-VC]{1,2})?(?<descriptor>(MI|PR|BC|DR|BL|SH|TS|FZ))(?<group>[A-Z]{2})+\s");



有当然还有其他办法,但这很容易理解。缺点是如果要添加新的描述符,必须更改表达式。



代码很简单。

匹配表达式,查找强度标识符,查找描述符,如果存在更多组,请查找它们并添加到输出中。

(请注意,我没有进行任何错误检查)


There is of course other ways to do it, but this easy to understand. The drawback is that if new descriptors will be added, the expression must be changed.

The code is pretty straight forward.
Match the expression, look up the intensity identifier, look up the descriptor and if more groups exist look them up and add to the output as well.
(Note that I didn't put in any error checks)

Match m = MetarExpression.Match(metar);
if (m.Success)
{
  StringBuilder sb = new StringBuilder();

  sb.Append(phenom[m.Groups["intensity"].Value]);
  sb.Append(" ");
  sb.Append(phenom[m.Groups["descriptor"].Value]);
  sb.Append(" ");

  foreach (Capture cap in m.Groups["group"].Captures)
  {
    sb.Append(phenom[cap.Value]);
    sb.Append(" ");
  }
  Console.WriteLine(sb);
  Console.WriteLine();
}



我使用了您为查询定义的词典。



打印输出将是:

重雷暴雨冰雹


I have used the dictionary you have defined for the look-up.

The printout will be:
Heavy Thunderstorm Rain Hail


这篇关于正则表达式与字典键匹配的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆