C#String替换为字典

我有一个字符串,我需要做一些替换。 我有一个Dictionary ,其中我定义了搜索替换对。 我创建了以下扩展方法来执行此操作:

 public static string Replace(this string str, Dictionary dict) { StringBuilder sb = new StringBuilder(str); return sb.Replace(dict).ToString(); } public static StringBuild Replace(this StringBuilder sb, Dictionary dict) { foreach (KeyValuePair replacement in dict) { sb.Replace(replacement.Key, replacement.Value); } return sb; } 

有没有更好的方法呢?

如果数据被标记化(即“亲爱的$ name $,从$ date $你的余额是$ amount $”),那么正则Regex可能是有用的:

 static readonly Regex re = new Regex(@"\$(\w+)\$", RegexOptions.Compiled); static void Main() { string input = @"Dear $name$, as of $date$ your balance is $amount$"; var args = new Dictionary( StringComparer.OrdinalIgnoreCase) { {"name", "Mr Smith"}, {"date", "05 Aug 2009"}, {"amount", "GBP200"} }; string output = re.Replace(input, match => args[match.Groups[1].Value]); } 

但是,如果没有这样的东西,我希望您的Replace循环可能与您可以做的一样多,而不会达到极限。 如果它没有被标记化,也许可以对其进行分析; Replace实际上是一个问题吗?

用Linq做到这一点:

 var newstr = dict.Aggregate(str, (current, value) => current.Replace(value.Key, value.Value)); 

dict是你的搜索替换对定义的Dictionary对象。

str是你需要做一些替换的字符串。

对我来说似乎是合理的,除了一件事:它对订单敏感。 例如,输入一个“$ x $ y”的输入字符串和一个替换字典:

 "$x" => "$y" "$y" => "foo" 

替换的结果 “foo foo”或“$ y foo”,具体取决于首先执行的替换。

您可以使用List>来控制排序。 另一种方法是遍历字符串,确保在进一步的替换操作中不使用替换。 但这可能要困难得多。

这是@ Marc的一个很好的重新考虑的版本@Marc的最佳答案,使function可用作Regex的扩展方法:

 static void Main() { string input = @"Dear $name$, as of $date$ your balance is $amount$"; var args = new Dictionary(StringComparer.OrdinalIgnoreCase); args.Add("name", "Mr Smith"); args.Add("date", "05 Aug 2009"); args.Add("amount", "GBP200"); Regex re = new Regex(@"\$(\w+)\$", RegexOptions.Compiled); string output = re.replaceTokens(input, args); // spot the LinqPad user // output.Dump(); } public static class ReplaceTokensUsingDictionary { public static string replaceTokens(this Regex re, string input, IDictionary args) { return re.Replace(input, match => args[match.Groups[1].Value]); } } 

使用Marc Gravell的RegEx解决方案时,首先使用ie ContainsKey检查令牌是否可用,这样可以防止KeyNotFoundException错误:

 string output = re.Replace(zpl, match => { return args.ContainsKey(match.Groups[1].Value) ? arg[match.Groups[1].Value] : match.Value; }); 

当使用以下略微修改的示例代码时(第一个参数有不同的名称):

  var args = new Dictionary( StringComparer.OrdinalIgnoreCase) { {"nameWRONG", "Mr Smith"}, {"date", "05 Aug 2009"}, {"AMOUNT", "GBP200"} }; 

这产生以下结果:

“亲爱的$ name $,截至2009年8月5日,您的余额为200英镑”

这个给你:

 public static class StringExm { public static String ReplaceAll(this String str, KeyValuePair[] map) { if (String.IsNullOrEmpty(str)) return str; StringBuilder result = new StringBuilder(str.Length); StringBuilder word = new StringBuilder(str.Length); Int32[] indices = new Int32[map.Length]; for (Int32 characterIndex = 0; characterIndex < str.Length; characterIndex++) { Char c = str[characterIndex]; word.Append(c); for (var i = 0; i < map.Length; i++) { String old = map[i].Key; if (word.Length - 1 != indices[i]) continue; if (old.Length == word.Length && old[word.Length - 1] == c) { indices[i] = -old.Length; continue; } if (old.Length > word.Length && old[word.Length - 1] == c) { indices[i]++; continue; } indices[i] = 0; } Int32 length = 0, index = -1; Boolean exists = false; for (int i = 0; i < indices.Length; i++) { if (indices[i] > 0) { exists = true; break; } if (-indices[i] > length) { length = -indices[i]; index = i; } } if (exists) continue; if (index >= 0) { String value = map[index].Value; word.Remove(0, length); result.Append(value); if (word.Length > 0) { characterIndex -= word.Length; word.Length = 0; } } result.Append(word); word.Length = 0; for (int i = 0; i < indices.Length; i++) indices[i] = 0; } if (word.Length > 0) result.Append(word); return result.ToString(); } }