C# 我怎样才能加快这个循环?是否有一个同时替换多个术语的类?

C# 我怎样才能加快这个循环?是否有一个同时替换多个术语的类?,c#,string,optimization,replace,C#,String,Optimization,Replace,循环: var pattern = _dict[key]; string before; do { before = pattern; foreach (var pair in _dict) if (key != pair.Key) pattern = pattern.Replace(string.Concat("{", pair.Key, "}"), string.Concat("(", pair.Value, ")")); } whil

循环:

var pattern = _dict[key];
string before;
do
{
    before = pattern;
    foreach (var pair in _dict)
        if (key != pair.Key)
            pattern = pattern.Replace(string.Concat("{", pair.Key, "}"), string.Concat("(", pair.Value, ")"));
} while (pattern != before);
return pattern;
它只是在一串键上重复查找和替换。这本词典就是

我可以看到这方面有两个改进

  • 每次执行
    pattern.Replace
    时,它都会从字符串的开头再次搜索。如果当它点击第一个
    {
    时,它只需在键列表中查找匹配项(可能使用二进制搜索),然后替换相应的键就更好了
  • pattern!=before
    位是我在迭代过程中检查是否替换了任何内容的方式。如果
    pattern.Replace
    函数返回了实际发生的替换数量或任何替换,我就不需要这个
  • 然而…我真的不想写一个大的讨厌的东西类来完成所有这些。这一定是一个相当常见的场景?有没有现成的解决方案


    全班 多亏了Elian Ebbing和ChrisWue

    class FlexDict : IEnumerable<KeyValuePair<string,string>>
    {
        private Dictionary<string, string> _dict = new Dictionary<string, string>();
        private static readonly Regex _re = new Regex(@"{([_a-z][_a-z0-9-]*)}", RegexOptions.Compiled | RegexOptions.IgnoreCase);
    
        public void Add(string key, string pattern)
        {
            _dict[key] = pattern;
        }
    
        public string Expand(string pattern)
        {
            pattern = _re.Replace(pattern, match =>
                {
                    string key = match.Groups[1].Value;
    
                    if (_dict.ContainsKey(key))
                        return "(" + Expand(_dict[key]) + ")";
    
                    return match.Value;
                });
    
            return pattern;
        }
    
        public string this[string key]
        {
            get { return Expand(_dict[key]); }
        }
    
        public IEnumerator<KeyValuePair<string, string>> GetEnumerator()
        {
            foreach (var p in _dict)
                yield return new KeyValuePair<string,string>(p.Key, this[p.Key]);
        }
    
        IEnumerator IEnumerable.GetEnumerator()
        {
            return GetEnumerator();
        }
    }
    
    类FlexDict:IEnumerable
    {
    专用词典_dict=新词典();
    私有静态只读Regex_re=newregex(@“{([[u a-z][[u a-z0-9-]*]),RegexOptions.Compiled | RegexOptions.IgnoreCase);
    公共void添加(字符串键、字符串模式)
    {
    _dict[键]=模式;
    }
    公共字符串扩展(字符串模式)
    {
    模式=\u re.Replace(模式,匹配=>
    {
    字符串键=匹配。组[1]。值;
    如果(_dict.ContainsKey(键))
    返回“(“+扩展(_dict[key])+”)”;
    返回match.Value;
    });
    回报模式;
    }
    公共字符串此[字符串键]
    {
    获取{return Expand(_dict[key]);}
    }
    公共IEnumerator GetEnumerator()
    {
    foreach(var p in_dict)
    返回新的KeyValuePair(p.Key,this[p.Key]);
    }
    IEnumerator IEnumerable.GetEnumerator()
    {
    返回GetEnumerator();
    }
    }
    
    示例用法
    类程序
    {
    静态void Main(字符串[]参数)
    {
    var flex=新FlexDict
    {
    {“h”@“[0-9a-f]”,
    {“nonascii”@“[\200-\377]”,
    {“unicode”、@“\{h}{1,6}(\r\n |[\t\r\n\f])?”,
    {“escape”@“{unicode}\\[^\r\n\f0-9a-f]”,
    {“nmstart”,
    {“nmchar”,
    {“string1”,“@”“”([^\n\r\f\\”“]\\{nl}{escape})*''},
    {“string2”、@“'([^\n\r\f\\']\\{nl}{escape})*'”,
    {“badstring1”,“@”“”([^\n\r\f\\”“]\\{nl}{escape})*\\?“},
    {“badstring2”、@“([^\n\r\f\\']\\{nl}{escape})*\\?”},
    {“badcomment1”,@/\*[^*]*\*+([^/*][^*]*\*+)*},
    {“badcomment2”,@/\*[^*]*(\*+[^/*][^*]*)*”,
    {“baduri1”,@“url\({w}([!\$%&*-\[\]-~]{nonascii}{escape})*{w},
    {“baduri2”,@“url\({w}{string}{w}}}),
    {“baduri3”,@“url\({w}{badstring}}),
    {“注释”@/\*[^*]*\*+([^/*][^*]*\*+)*/“},
    {“ident”,@-?{nmstart}{nmchar}*“},
    {name',@{nmchar}+},
    {“num”,@“[0-9]+|[0-9]*\.[0-9]+”},
    {“字符串”@“{string1}{string2}”},
    {“badstring”、@“{badstring1}{badstring2}”,
    {“badcomment”、@{badcomment1}{badcomment2},
    "巴杜里","巴杜里1","巴杜里2","巴杜里3",,
    {“url”、@“([!$%&*-~]{nonascii}{escape})*”,
    {“s”@“[\t\r\n\f]+”},
    {w',@{s}?},
    {“nl”@“\n |\r\n |\r |\f”},
    {“A”、@“A |\\0{0,4}(41 | 61)(\r\n |[\t\r\n\f])?”,
    {“C”、@“C|\\0{0,4}(43|63)(\r\n|[\t\r\n\f])?”,
    {D',@“D| \\0{0,4}(44|64)(\r\n|[\t\r\n\f])?”,
    {“E”,@“E |\\0{0,4}(45 | 65)(\r\n |[\t\r\n\f])?”,
    {“G”、@“G”\\0{0,4}(47 | 67)(\r\n |[\t\r\n\f])?|\\G},
    {“H”、@“H |\\0{0,4}(48 | 68)(\r\n |[\t\r\n\f])?|\\H},
    {“I”、@“I|\\0{0,4}(49|69)(\r\n|[\t\r\n\f])?|\\I},
    {“K”、@“K|\\0{0,4}(4b|6b)(\r\n|[\t\r\n\f])?|\\K},
    {L',@“L|\\0{0,4}(4c|6c)(\r\n|[\t\r\n\f])?|\\L},
    {“M”、@“M|\\0{0,4}(4d|6d)(\r\n|[\t\r\n\f])?|\\M},
    {“N”,@“N|\\0{0,4}(4e|6e)(\r\N|[\t\r\N\f])?|\\N},
    {O',@“O|\\0{0,4}(4f|6f)(\r\n|[\t\r\n\f])?|\\O},
    {“P”、@“P|\\0{0,4}(50|70)(\r\n|[\t\r\n\f])?|\\P},
    {“R”、@“R|\\0{0,4}(52|72)(\R\n|[\t\R\n\f])?|\\R},
    {S',@“S|\\0{0,4}(53|73)(\r\n|[\t\r\n\f])?|\\S},
    {“T”、@“T|\\0{0,4}(54|74)(\r\n|[\T\r\n\f])?|\\T},
    {“U”、@“U|\\0{0,4}(55|75)(\r\n|[\t\r\n\f])?|\\U},
    {“X”、@“X”\\0{0,4}(58 | 78)(\r\n |[\t\r\n\f])?|\\X},
    {“Z”、@“Z”\\0{0,4}(5a|7a)(\r\n|[\t\r\n\f])?|\\Z},
    {“Z”、@“Z”\\0{0,4}(5a|7a)(\r\n|[\t\r\n\f])?|\\Z},
    {“CDO”,@'},
    {“包括”、@“~=”},
    {“DASHMATCH”,@“\\\=”},
    {STRING',@{STRING},
    {“坏字符串”@“{badstring}”},
    {IDENT',@{IDENT},
    {“散列”@“{name}”},
    {“导入”、@{I}{M}{P}{O}{R}{T},
    {“PAGE_SYM”,@{P}{A}{G}{E},
    {“媒体”{M}{E}{D}{I}{A}},
    {“CHARSET_SYM”@“@CHARSET\b”},
    ("重要","重要","("评论"),"重要","重要"("评论),"重要",,
    {EMS',@{num}{E}{M},
    {EXS',@{num}{E}{X},
    {“长度”,
    {“角度”,
    {“时间”,
    {“百分比”,@{num}%},
    {NUMBER',@{num}},
    {“URI”,@{U}{R}{L}\({w}{stri
    
    class Program
    {
        static void Main(string[] args)
        {
            var flex = new FlexDict
                {
                    {"h", @"[0-9a-f]"},
                    {"nonascii", @"[\200-\377]"},
                    {"unicode", @"\\{h}{1,6}(\r\n|[ \t\r\n\f])?"},
                    {"escape", @"{unicode}|\\[^\r\n\f0-9a-f]"},
                    {"nmstart", @"[_a-z]|{nonascii}|{escape}"},
                    {"nmchar", @"[_a-z0-9-]|{nonascii}|{escape}"},
                    {"string1", @"""([^\n\r\f\\""]|\\{nl}|{escape})*"""},
                    {"string2", @"'([^\n\r\f\\']|\\{nl}|{escape})*'"},
                    {"badstring1", @"""([^\n\r\f\\""]|\\{nl}|{escape})*\\?"},
                    {"badstring2", @"'([^\n\r\f\\']|\\{nl}|{escape})*\\?"},
                    {"badcomment1", @"/\*[^*]*\*+([^/*][^*]*\*+)*"},
                    {"badcomment2", @"/\*[^*]*(\*+[^/*][^*]*)*"},
                    {"baduri1", @"url\({w}([!#$%&*-\[\]-~]|{nonascii}|{escape})*{w}"},
                    {"baduri2", @"url\({w}{string}{w}"},
                    {"baduri3", @"url\({w}{badstring}"},
                    {"comment", @"/\*[^*]*\*+([^/*][^*]*\*+)*/"},
                    {"ident", @"-?{nmstart}{nmchar}*"},
                    {"name", @"{nmchar}+"},
                    {"num", @"[0-9]+|[0-9]*\.[0-9]+"},
                    {"string", @"{string1}|{string2}"},
                    {"badstring", @"{badstring1}|{badstring2}"},
                    {"badcomment", @"{badcomment1}|{badcomment2}"},
                    {"baduri", @"{baduri1}|{baduri2}|{baduri3}"},
                    {"url", @"([!#$%&*-~]|{nonascii}|{escape})*"},
                    {"s", @"[ \t\r\n\f]+"},
                    {"w", @"{s}?"},
                    {"nl", @"\n|\r\n|\r|\f"},
    
                    {"A", @"a|\\0{0,4}(41|61)(\r\n|[ \t\r\n\f])?"},
                    {"C", @"c|\\0{0,4}(43|63)(\r\n|[ \t\r\n\f])?"},
                    {"D", @"d|\\0{0,4}(44|64)(\r\n|[ \t\r\n\f])?"},
                    {"E", @"e|\\0{0,4}(45|65)(\r\n|[ \t\r\n\f])?"},
                    {"G", @"g|\\0{0,4}(47|67)(\r\n|[ \t\r\n\f])?|\\g"},
                    {"H", @"h|\\0{0,4}(48|68)(\r\n|[ \t\r\n\f])?|\\h"},
                    {"I", @"i|\\0{0,4}(49|69)(\r\n|[ \t\r\n\f])?|\\i"},
                    {"K", @"k|\\0{0,4}(4b|6b)(\r\n|[ \t\r\n\f])?|\\k"},
                    {"L", @"l|\\0{0,4}(4c|6c)(\r\n|[ \t\r\n\f])?|\\l"},
                    {"M", @"m|\\0{0,4}(4d|6d)(\r\n|[ \t\r\n\f])?|\\m"},
                    {"N", @"n|\\0{0,4}(4e|6e)(\r\n|[ \t\r\n\f])?|\\n"},
                    {"O", @"o|\\0{0,4}(4f|6f)(\r\n|[ \t\r\n\f])?|\\o"},
                    {"P", @"p|\\0{0,4}(50|70)(\r\n|[ \t\r\n\f])?|\\p"},
                    {"R", @"r|\\0{0,4}(52|72)(\r\n|[ \t\r\n\f])?|\\r"},
                    {"S", @"s|\\0{0,4}(53|73)(\r\n|[ \t\r\n\f])?|\\s"},
                    {"T", @"t|\\0{0,4}(54|74)(\r\n|[ \t\r\n\f])?|\\t"},
                    {"U", @"u|\\0{0,4}(55|75)(\r\n|[ \t\r\n\f])?|\\u"},
                    {"X", @"x|\\0{0,4}(58|78)(\r\n|[ \t\r\n\f])?|\\x"},
                    {"Z", @"z|\\0{0,4}(5a|7a)(\r\n|[ \t\r\n\f])?|\\z"},
                    {"Z", @"z|\\0{0,4}(5a|7a)(\r\n|[ \t\r\n\f])?|\\z"},
    
                    {"CDO", @"<!--"},
                    {"CDC", @"-->"},
                    {"INCLUDES", @"~="},
                    {"DASHMATCH", @"\|="},
                    {"STRING", @"{string}"},
                    {"BAD_STRING", @"{badstring}"},
                    {"IDENT", @"{ident}"},
                    {"HASH", @"#{name}"},
                    {"IMPORT_SYM", @"@{I}{M}{P}{O}{R}{T}"},
                    {"PAGE_SYM", @"@{P}{A}{G}{E}"},
                    {"MEDIA_SYM", @"@{M}{E}{D}{I}{A}"},
                    {"CHARSET_SYM", @"@charset\b"},
                    {"IMPORTANT_SYM", @"!({w}|{comment})*{I}{M}{P}{O}{R}{T}{A}{N}{T}"},
                    {"EMS", @"{num}{E}{M}"},
                    {"EXS", @"{num}{E}{X}"},
                    {"LENGTH", @"{num}({P}{X}|{C}{M}|{M}{M}|{I}{N}|{P}{T}|{P}{C})"},
                    {"ANGLE", @"{num}({D}{E}{G}|{R}{A}{D}|{G}{R}{A}{D})"},
                    {"TIME", @"{num}({M}{S}|{S})"},
                    {"PERCENTAGE", @"{num}%"},
                    {"NUMBER", @"{num}"},
                    {"URI", @"{U}{R}{L}\({w}{string}{w}\)|{U}{R}{L}\({w}{url}{w}\)"},
                    {"BAD_URI", @"{baduri}"},
                    {"FUNCTION", @"{ident}\("},
                };
    
            var testStrings = new[] { @"""str""", @"'str'", "5", "5.", "5.0", "a", "alpha", "url(hello)", 
                "url(\"hello\")", "url(\"blah)", @"\g", @"/*comment*/", @"/**/", @"<!--", @"-->", @"~=",
                "|=", @"#hash", "@import", "@page", "@media", "@charset", "!/*iehack*/important"};
    
            foreach (var pair in flex)
            {
                Console.WriteLine("{0}\n\t{1}\n", pair.Key, pair.Value);
            }
    
            var sw = Stopwatch.StartNew();
            foreach (var str in testStrings)
            {
                Console.WriteLine("{0} matches: ", str);
                foreach (var pair in flex)
                {
                    if (Regex.IsMatch(str, "^(" + pair.Value + ")$", RegexOptions.IgnoreCase | RegexOptions.ExplicitCapture))
                        Console.WriteLine("  {0}", pair.Key);
                }
            }
            Console.WriteLine("\nRan in {0} ms", sw.ElapsedMilliseconds);
            Console.ReadLine();
        }
    }
    
    var pattern = _dict[key];
    bool isChanged = false;
    
    do
    {
        isChanged = false;
    
        pattern = Regex.Replace(pattern, "{([^}]+)}", match => {
            string matchKey = match.Groups[1].Value;
    
            if (matchKey != key && _dict.ContainsKey(matchKey))
            {
                isChanged = true;
                return "(" + _dict[matchKey] + ")";
            }
    
            return match.Value;
        });
    } while (isChanged);
    
    var keys = dict.KeyCollection.Where(k => k != key);
    bool replacementMade = keys.Any();
    
    foreach(var k in keys.AsParallel(), () => {replacement code})
    
    var pattern = _dict[key];
    bool replaced = false;
    do {
      pattern = Regex.Replace(pattern, @"\{([^\}]+)\}", m => {
        string k = m.Groups[1].Value;
        string value;
        if (k != key && _dict.TryGetValue(k, out value) {
          replaced = true;
          return "(" + value + ")";
        } else {
          return "{" + k + "}";
        }
      });
    } while (replaced);
    return pattern;