假设我有一个文本模板,其中包含许多需要填充的字段:
var template = "hello {$name}. you are {$age} years old. you live in {$location}"
和要替换的IDictionary<string,string>
值:
key | value
===================
name | spender
age | 38
location| UK
填充模板的天真方式可能是:
var output = template;
foreach(var kvp in templValues)
{
output = output.Replace(string.format("{{${0}}}", kvp.Key), kvp.Value);
}
但是,这似乎效率低下。还有更好的方法吗?
答案 0 :(得分:4)
您可以使用Regex.Replace()
,如下所示:
var output = new Regex(@"\{\$([^}]+)\}").Replace(
template,
m => templValues.ContainsKey(m.Captures[1].Value)
? templValues[m.Captures[1].Value]
: m.Value);
AFAIK如果您的字典是这样构建的,这也可以防止出现意外结果,因为这可能会产生"hello UK. you are 38 years old. you live in UK"
以及"hello {$location}. you are 38 years old. you live in UK"
,因为dictionarys不会对其键进行排序:
key | value
===================
name | {$location}
age | 38
location| UK
当实际需要第一个行为时,您可以多次运行正则表达式。
编辑:如果模板解析实际上是代码的时间关键部分,那么不要在那里进行模板解析。你应该考虑使用手动解析方法Sean推荐。
答案 1 :(得分:0)
如果您担心性能,一次性手动解析模板可能是最快的:
static string DictFormat(string template, IDictionary<string, string> dict) {
const string left_delimiter = "{$";
int left_delimiter_len = left_delimiter.Length;
const string right_delimiter = "}";
int right_delimiter_len = right_delimiter.Length;
var sb = new StringBuilder();
int end = 0;
while (true) {
int start = template.IndexOf(left_delimiter, end);
if (start >= 0) {
sb.Append(template.Substring(end, start - end));
start += left_delimiter_len;
end = template.IndexOf(right_delimiter, start);
if (end >= 0) {
string key = template.Substring(start, end - start);
string value;
if (dict.TryGetValue(key, out value)) {
sb.Append(value);
end += right_delimiter_len;
}
else
throw new ArgumentException(string.Format("Key not found: {0}", key), "template");
}
else
throw new ArgumentException(string.Format("Key starting at {0} not properly closed.", start), "template");
}
else {
sb.Append(template.Substring(end));
return sb.ToString();
}
}
}
像这样使用:
const string template = "hello {$name}. you are {$age} years old. you live in {$location}";
var dict = new Dictionary<string, string> { { "name", "spender" }, { "age", "38" }, { "location", "UK" } };
string result = DictFormat(template, dict);
答案 2 :(得分:-2)
冒着愚蠢的风险,你可以写一个函数来返回你想要的字符串:
public string CreateString(string name, string age, string location)
{
return "hello " + name + ". you are " + age + " years old. you live in " + location;
}
由于您只能在字典中存储一组值,因此以这种方式使用模板的值似乎会减少。