正则表达式使用字典对查找匹配项

本文关键字:查找 字典 正则表达式 | 更新日期: 2023-09-27 17:53:33

我是c#及其正则表达式功能的新手。基本上,我想使用以下字典并将其与一些正则表达式进行匹配,以查看这样的字符串是否存在于字符串中。

// weather phenomenons
Dictionary<string, object> wxMap = new Dictionary<string, object> {
    {"MI", "shallow "},
    {"BL", "blowing "},
    {"BC", "patches "},
    {"SH", "showers "},
    {"PR", "partials "},
    {"DR", "drifting "},
    {"TS", "thunderstorm "},
    {"FZ", "freezing "},
    {"DZ", "drizzle "},
    {"IC", "ice crystals "},
    {"UP", "unknown "},
    {"RA", "rain "},
    {"PL", "ice pellets "},
    {"SN", "snow "},
    {"GR", "hail "},
    {"SG", "snow grains "},
    {"GS", "small hail/snow pellets "},
    {"BR", "mist "},
    {"SA", "sand "},
    {"FU", "smoke "},
    {"HZ", "haze "},
    {"FG", "fog "},
    {"VA", "volcanic ash "},
    {"PY", "spray "},
    {"DU", "widespread dust "},
    {"SQ", "squall "},
    {"FC", "funnel cloud "},
    {"SS", "sand storm "},
    {"DS", "dust storm "},
    {"PO", "well developed dust/sand swirls "},
    {"VC", "vicinity "},
    {"RE", "recent "}
};

我想匹配一个METAR字符串,它可能有也可能没有这些现象。

KLAX 260053Z 27012KT 10SM -SN BR BKN017 OVC200 16/11 A2992 RMK AO2 SLP132 T01560111

如果我有以下PHP(从这里取的),但我不确定如何准确地转换它,所以它会从字典中选择正确的现象(我也想注入Heavy/Light/Vicinity字符串,太)。

public $texts=Array('MI'=>'Shallow','PR'=>'Partial','BC'=>'Low drifting','BL'=>'Blowing',
        'SH'=>'Showers','TS'=>'Thunderstorm','FZ'=>'Freezing','DZ'=>'Drizzle','RA'=>'Rain','SN'=>'Snow',
        'SG'=>'Snow Grains','IC'=>'Ice crystals','PL'=>'Ice pellets','GR'=>'Hail','GS'=>'Small hail',
        'UP'=>'Unknown','BR'=>'Mist','FG'=>'Fog','FU'=>'Smoke','VA'=>'Volcanic ash','DU'=>'Widespread dust',
        'SA'=>'Sand','HZ'=>'Haze','PY'=>'Spray','PO'=>'Well developed dust / sand whirls','SQ'=>'Squalls',
        'FC'=>'Funnel clouds inc tornadoes or waterspouts','SS'=>'Sandstorm','DS'=>'Duststorm');
if(preg_match('#^('+|'-|VC)?('.implode('|',array_keys($this->texts)).')('.implode('|',array_keys($this->texts)).')?$#',$code,$matches))
{
    $text=Array();
    switch($matches[1]) {
        case '+':
            $text[]='Heavy';
            break;
        case '-':
            $text[]='Light';
            break;
        case 'VC':
            $text[]='Vicinity';
            break;
        default:
            break;
    }
    if($matches[2])
        $text[]=$this->texts[$matches[2]];
    if($matches[3])
        $text[]=$this->texts[$matches[3]];
    $this->addWeather(implode(' ',$text));
    return;
}
基本上,这将解析METAR(使用正则表达式匹配现象部分),例如,包含了KLAX METAR I,它将返回小雪

如果有人能在正确的道路上帮助我,我将不胜感激。

正则表达式使用字典对查找匹配项

c#中直接等效的代码是:

class Program
{
    static Dictionary<string, object> wxMap = new Dictionary<string, object> 
    {
        {"MI", "shallow "},
        {"BL", "blowing "},
        {"BC", "patches "},
        {"SH", "showers "},
        {"PR", "partials "},
        {"DR", "drifting "},
        {"TS", "thunderstorm "},
        {"FZ", "freezing "},
        {"DZ", "drizzle "},
        {"IC", "ice crystals "},
        {"UP", "unknown "},
        {"RA", "rain "},
        {"PL", "ice pellets "},
        {"SN", "snow "},
        {"GR", "hail "},
        {"SG", "snow grains "},
        {"GS", "small hail/snow pellets "},
        {"BR", "mist "},
        {"SA", "sand "},
        {"FU", "smoke "},
        {"HZ", "haze "},
        {"FG", "fog "},
        {"VA", "volcanic ash "},
        {"PY", "spray "},
        {"DU", "widespread dust "},
        {"SQ", "squall "},
        {"FC", "funnel cloud "},
        {"SS", "sand storm "},
        {"DS", "dust storm "},
        {"PO", "well developed dust/sand swirls "},
        {"VC", "vicinity "},
        {"RE", "recent "}
    };
    static string Process(String metar)
    {
        string pattern = @"('+|'-|VC)?(" + String.Join("|", wxMap.Keys) + ") (" + String.Join("|", wxMap.Keys) + ")?";
        StringBuilder result = new StringBuilder();
        Regex r = new Regex(pattern);
        Match mc = r.Match(metar);
        GroupCollection gc = mc.Groups;
        switch(gc[1].Value)
        {
            case "+":
                result.Append("Heavy");
                break;
            case "-":
                result.Append("Light");
                break;
            case "VC":
                result.Append("Vicinity");
                break;
            default:
                break;
        }
        result.AppendFormat(" {0}", wxMap[gc[2].Value]);
        if(gc.Count > 2)
            result.AppendFormat("and {0}", wxMap[gc[3].Value]);
        return result.ToString();
    }
    static void Main()
    {
        string output = Process("KLAX 260053Z 27012KT 10SM -SN BR BKN017 OVC200 16/11 A2992 RMK AO2 SLP132 T01560111");
        Console.WriteLine(output);
    }

我认为这个问题很适合使用LINQ .试试这个代码:

var input= "KLAX 260053Z 27012KT 10SM -SN BR BKN017 OVC200 16/11 A2992 RMK AO2 SLP132 T01560111";
var pairs = new Dictionary<string, string>
        {
            {"+", "Heavy"}, 
            {"-", "Light"}, 
            {"VC", "Vicinity"}
        };
var result = input.Split()
        .Where(x => wxMap.Keys.Any(x.Contains))
        .Select(x =>
        {
            if (x.Length == 2) return wxMap[x];
            if (x.Length == 3) 
                return pairs[x[0].ToString()] + " " + wxMap[x.Substring(1)];
            if (x.Length == 4)
                return pairs[x[0].ToString() + x[1]] + " " + wxMap[x.Substring(2)];
            return string.Empty;
        });
var output = string.Join(" ", result); // Light snow  mist  

注意:这个答案假设所有后缀(-, +VC)出现在实际的Key之前。例如,如果您的输入字符串包含SN-,这将不起作用,并抛出异常。

我的想法与selman22相同,使用条件"levels"的字典:

var levels = new Dictionary<string, object>
{
    { "", "" },
    { "-", "Light" },
    { "+", "Heavy" },
    { "VC", "Vicinity" }
};

您可以使用LINQ查询语法连接您的级别,条件和METAR字符串(在空间上分割):

var conditions
    = string.Join("and ", from l in levels.Keys
                          from w in wxMap.Keys
                          join m in metar.Split() on string.Concat(l, w) equals m
                          select string.Concat(levels[l], wxMap[w]));

输出(使用示例字符串):

薄雾和小雪