C# 将参数命名为替换参数值的字符串
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/379328/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
C# Named parameters to a string that replace to the parameter values
提问by
I want in a good performance way (I hope) replace a named parameter in my string to a named parameter from code, example, my string:
我希望以一种良好的性能方式(我希望)将我的字符串中的命名参数替换为代码中的命名参数,例如我的字符串:
"Hi {name}, do you like milk?"
How could I replace the {name} by code, Regular expressions? To expensive? Which way do you recommend?
我怎么能用代码,正则表达式替换 {name} ?贵吗?你推荐哪种方式?
How do they in example NHibernates HQL to replace :my_param to the user defined value? Or in ASP.NET (MVC) Routing that I like better, "{controller}/{action}", new { controller = "Hello", ... }?
他们如何在示例 NHibernates HQL 中将 :my_param 替换为用户定义的值?或者在我更喜欢的 ASP.NET (MVC) 路由中,"{controller}/{action}", new { controller = "Hello", ... }?
采纳答案by Konrad Rudolph
Have you confirmed that regular expressions are too expensive?
你确认正则表达式太贵了吗?
The cost of regular expressions is greatly exaggerated. For such a simple pattern performance will be quite good, probably only slightly less good than direct search-and-replace, in fact. Also, have you experimented with the Compiled
flag when constructing the regular expression?
正则表达式的成本被大大夸大了。对于这样一个简单的模式,性能会非常好,实际上可能只比直接搜索替换略差一点。另外,您Compiled
在构建正则表达式时是否尝试过标志?
That said, can't you just use the simplest way, i.e. Replace
?
也就是说,你不能只使用最简单的方法,即Replace
?
string varname = "name";
string pattern = "{" + varname + "}";
Console.WriteLine("Hi {name}".Replace(pattern, "Mike"));
回答by Andrew Hare
A compiled regex might do the trick , especially if there are many tokens to be replaced. If there are just a handful of them and performance is key, I would simply find the token by index and replace using string functions. Believe it or not this will be faster than a regex.
编译后的正则表达式可能会奏效,尤其是在有许多标记要替换的情况下。如果只有少数几个并且性能是关键,我会简单地通过索引找到令牌并使用字符串函数替换。信不信由你,这将比正则表达式更快。
回答by Marc Gravell
Regex is certainly a viable option, especially with a MatchEvaluator
:
正则表达式当然是一个可行的选择,尤其是对于MatchEvaluator
:
Regex re = new Regex(@"\{(\w*?)\}", RegexOptions.Compiled); // store this...
string input = "Hi {name}, do you like {food}?";
Dictionary<string, string> vals = new Dictionary<string, string>();
vals.Add("name", "Fred");
vals.Add("food", "milk");
string q = re.Replace(input, delegate(Match match)
{
string key = match.Groups[1].Value;
return vals[key];
});
回答by James Curran
Now if you have you replacements in a dictionary, like this:
现在,如果您在字典中有替换项,如下所示:
var replacements = new Dictionary<string, string>();
replacements["name"] = "Mike";
replacements["age"]= "20";
then the Regex becomes quite simple:
然后正则表达式变得非常简单:
Regex regex = new Regex(@"\{(?<key>\w+)\}");
string formattext = "{name} is {age} years old";
string newStr = regex.Replace(formattext,
match=>replacements[match.Groups[1].Captures[0].Value]);
回答by James Curran
Try using StringTemplate. It's much more powerful than that, but it does the job flawless.
尝试使用 StringTemplate。它比那强大得多,但它可以完美地完成工作。
回答by sosdude
How about
怎么样
stringVar = "Hello, {0}. How are you doing?";
arg1 = "John"; // or args[0]
String.Format(stringVar, arg1)
You can even have multiple args, just increment the {x} and add another parameter to the Format() method. Not sure the different but both "string" and "String" have this method.
您甚至可以有多个参数,只需增加 {x} 并向 Format() 方法添加另一个参数。不确定不同,但“字符串”和“字符串”都有这种方法。
回答by mindplay.dk
After thinking about this, I realized what I actually wished for, was that String.Format() would take an IDictionary as argument, and that templates could be written using names instead of indexes.
考虑到这一点后,我意识到我真正想要的是 String.Format() 将 IDictionary 作为参数,并且可以使用名称而不是索引来编写模板。
For string substitutions with lots of possible keys/values, the index numbers result in illegible string templates - and in some cases, you may not even know which items are going to have what number, so I came up with the following extension:
对于具有许多可能的键/值的字符串替换,索引号会导致难以辨认的字符串模板 - 在某些情况下,您甚至可能不知道哪些项目将具有什么编号,因此我想出了以下扩展名:
https://gist.github.com/896724
https://gist.github.com/896724
Basically this lets you use string templates with names instead of numbers, and a dictionary instead of an array, and lets you have all the other good features of String.Format(), allowing the use of a custom IFormatProvider, if needed, and allowing the use of all the usual formatting syntax - precision, length, etc.
基本上,这使您可以使用带有名称而不是数字的字符串模板,以及使用字典而不是数组,并让您拥有 String.Format() 的所有其他优秀功能,允许使用自定义 IFormatProvider,如果需要,并允许使用所有常用的格式化语法——精度、长度等。
The exampleprovided in the reference material for String.Format is a great example of how templates with many numbered items become completely illegible - porting that example to use this new extension method, you get something like this:
String.Format 参考材料中提供的示例是一个很好的示例,说明带有许多编号项的模板如何变得完全难以辨认——移植该示例以使用这种新的扩展方法,您会得到如下内容:
var replacements = new Dictionary<String, object>()
{
{ "date1", new DateTime(2009, 7, 1) },
{ "hiTime", new TimeSpan(14, 17, 32) },
{ "hiTemp", 62.1m },
{ "loTime", new TimeSpan(3, 16, 10) },
{ "loTemp", 54.8m }
};
var template =
"Temperature on {date1:d}:\n{hiTime,11}: {hiTemp} degrees (hi)\n{loTime,11}: {loTemp} degrees (lo)";
var result = template.Subtitute(replacements);
As someone pointed out, if what you're writing needs to be highly optimized, don't use something like this - if you have to format millions of strings this way, in a loop, the memory and performance overhead could be significant.
正如有人指出的那样,如果您正在编写的内容需要高度优化,请不要使用这样的东西 - 如果您必须以这种方式格式化数百万个字符串,那么在循环中,内存和性能开销可能会很大。
On the other hand, if you're concerned about writing legible, maintainable code - and if you're doing, say, a bunch of database operations, in the grand scheme of things, this function will not add any significant overhead.
另一方面,如果您关心编写清晰易读、可维护的代码 - 并且如果您正在执行一系列数据库操作,那么从总体上看,此功能不会增加任何显着的开销。
...
...
For convenience, I did attempt to add a method that would accept an anonymous object instead of a dictionary:
为方便起见,我确实尝试添加一个接受匿名对象而不是字典的方法:
public static String Substitute(this String template, object obj)
{
return Substitute(
template,
obj.GetType().GetProperties().ToDictionary(p => p.Name, p => p.GetValue(obj, null))
);
}
For some reason, this doesn't work - passing an anonymous object like new { name: "value" }
to that extension method gives a compile-time error message saying the best match was the IDictionary version of that method. Not sure how to fix that. (anyone?)
出于某种原因,这不起作用 - 将匿名对象传递new { name: "value" }
给该扩展方法会给出编译时错误消息,说明最佳匹配是该方法的 IDictionary 版本。不知道如何解决这个问题。(任何人?)
回答by Allen Wang
or try this with Linq if you have all your replace values stored in a Dictionary obj.
或者如果您将所有替换值都存储在 Dictionary obj 中,请使用 Linq 尝试此操作。
For example:
例如:
Dictionary<string,string> dict = new Dictionary<string,string>();
dict.add("replace1","newVal1");
dict.add("replace2","newVal2");
dict.add("replace3","newVal3");
var newstr = dict.Aggregate(str, (current, value) => current.Replace(value.Key, value.Value));
dictis your search-replace pairs defined Dictionary object. stris your string which you need to do some replacements with.
dict是您的搜索替换对定义的 Dictionary 对象。 str是您需要对其进行一些替换的字符串。
回答by Edwin
I would go for the mindplay.dk solution... Works quite well.
我会选择 mindplay.dk 解决方案......效果很好。
And, with a slight modification, it supports templates-of-templates, like "Hi {name}, do you like {0}?", replacing {name} but retaining {0}:
并且,稍作修改,它支持模板的模板,如“嗨{name},你喜欢{0}吗?”,替换{name}但保留{0}:
In the given source (https://gist.github.com/896724), replace as follows:
在给定的源 ( https://gist.github.com/896724) 中,替换如下:
var format = Pattern.Replace(
template,
match =>
{
var name = match.Groups[1].Captures[0].Value;
if (!int.TryParse(name, out parsedInt))
{
if (!map.ContainsKey(name))
{
map[name] = map.Count;
list.Add(dictionary.ContainsKey(name) ? dictionary[name] : null);
}
return "{" + map[name] + match.Groups[2].Captures[0].Value + "}";
}
else return "{{" + name + "}}";
}
);
Furthermore, it supports a length ({name,30}) as well as a formatspecifier, or a combination of both.
此外,它支持长度 ({name,30}) 以及格式说明符,或两者的组合。