我有一个大文本模板,需要将标记化的部分替换为其他文本。令牌看起来像这样:## USERNAME ##。我的第一直觉只是使用String.Replace(),但是有更好,更有效的方法还是已经为此优化的Replace()?
答案 0 :(得分:12)
System.Text.RegularExpressions.Regex.Replace()就是你所寻找的 - 如果你的代币很奇怪你需要一个正则表达式才能找到它们。
Some kind soul did some performance testing,在Regex.Replace(),String.Replace()和StringBuilder.Replace()之间,String.Replace()实际上名列前茅。
答案 1 :(得分:7)
我必须这样做的唯一情况是发送模板化的电子邮件。在.NET中,MailDefinition class提供了开箱即用的功能。这就是你创建模板化消息的方式:
MailDefinition md = new MailDefinition();
md.BodyFileName = pathToTemplate;
md.From = "test@somedomain.com";
ListDictionary replacements = new ListDictionary();
replacements.Add("<%To%>", someValue);
// continue adding replacements
MailMessage msg = md.CreateMailMessage("test@someotherdomain.com", replacements, this);
在此之后,将通过替换模板中的值来创建msg.Body。我想你可以看一下使用Reflector :)的MailDefinition.CreateMailMessage()。很抱歉有点偏离主题,但如果这是你的情景,我认为这是最简单的方法。
答案 2 :(得分:3)
嗯,取决于模板中有多少变量,有多少模板等,这可能是完整模板处理器的工作。我用过.NET的唯一一个是NVelocity,但我确信其中有很多其他的,其中大多数都链接到某个Web框架或其他框架。
答案 3 :(得分:2)
string.Replace很好。我更喜欢使用正则表达式,但我是正则表达式的***。
要记住的是这些模板有多大。如果它真的很大,而内存是个问题,您可能想要创建一个作用于流的自定义标记生成器。这样,在操作它时,您只能将文件的一小部分保存在内存中。
但是,对于naiive实现,string.Replace应该没问题。
答案 4 :(得分:2)
如果你在大字符串上进行多次替换,那么使用StringBuilder.Replace()可能会更好,因为字符串的常见性能问题会出现。
答案 5 :(得分:2)
最近不得不做类似的事情。我做的是:
完成; - )
如果您想测试正则表达式,我可以建议the regulator.
答案 6 :(得分:2)
正则表达式是最快的代码解决方案,但如果你有许多不同的令牌,那么它会变慢。如果性能不是问题,那么使用此选项。
更好的方法是定义令牌,就像您可以在文本中扫描的“##”一样。然后从哈希表中选择要替换的内容,并将令牌后面的文本作为键。
如果这是构建脚本的一部分,那么nAnt有一个很棒的功能,称为Filter Chains。这个代码是开源的,所以你可以看看它是如何快速实现的。
答案 7 :(得分:2)
FastReplacer在O(n * log(n)+ m)时间内实现令牌替换,并使用原始字符串的3倍内存。
当性能很重要时,FastReplacer适用于对大字符串执行许多Replace操作。
主要思想是避免每次更换字符串时修改现有文本或分配新内存。
我们设计了FastReplacer来帮助我们完成一个项目,我们必须生成一个包含大量追加和替换操作的大文本。应用程序的第一个版本花了20秒使用StringBuilder生成文本。使用String类的第二个改进版本耗时10秒。然后我们实现了FastReplacer,持续时间降至0.1秒。
答案 8 :(得分:1)
如果你的模板很大且你有很多令牌,你可能不想走它并逐个替换模板中的令牌,因为这将导致O(N * M)操作,其中N是模板的大小,M是要替换的标记的数量。
以下方法接受您要替换的键值对的模板和字典。通过将StringBuilder初始化为略大于模板的大小,它应该导致O(N)操作(即它不应该自己增长N次)。
最后,您可以将令牌的构建移动到Singleton中,因为它只需要生成一次。
static string SimpleTemplate(string template, Dictionary<string, string> replacements)
{
// parse the message into an array of tokens
Regex regex = new Regex("(##[^#]+##)");
string[] tokens = regex.Split(template);
// the new message from the tokens
var sb = new StringBuilder((int)((double)template.Length * 1.1));
foreach (string token in tokens)
sb.Append(replacements.ContainsKey(token) ? replacements[token] : token);
return sb.ToString();
}
答案 9 :(得分:0)
这是正则表达式的理想用法。查看this helpful website,.Net Regular Expressions class以及这本非常有用的书Mastering Regular Expressions。