在模板中替换字符串的最快方法

时间:2022-11-26 01:34:48

I have some template string

我有一些模板字符串

this is my {0} template {1} string

这是我的{0}模板{1}字符串

which I plan to put user values in using String.Format().

我计划将用户值放在String.Format()中。

The string actually is longer so for readability I use:

字符串实际上更长,所以为了便于阅读我使用:

this is my {goodName1} template {goodName2} string

这是我的{goodName1}模板{goodName2}字符串

And then String.Replace each parameter with its value.

然后String.Replace每个参数及其值。

How can I get the highest performance and readability?

如何获得最高性能和可读性?

Maybe I should not have this template in a file (as now) but dynamically build it by concatanating to a string builder and adding the params when required? Although it's less readable.

也许我不应该在文件中使用此模板(如现在),但通过连接到字符串生成器并在需要时添加参数来动态构建它?虽然它的可读性较差。

What's my other options?

我的其他选择是什么?

9 个解决方案

#1


From Atwood: It. Just. Doesn't. Matter.

来自阿特伍德:它。只是。不。物。

#2


You can put the parameters in a dictionary and use the Regex.Replace method to replace all of the parameters in one replacement. That way the method scales well if the template string gets long or the number of parameters grows.

您可以将参数放在字典中,并使用Regex.Replace方法替换一个替换中的所有参数。这样,如果模板字符串变长或参数数量增加,该方法可以很好地扩展。

Example:

Dictionary<string, string> parameters = new Dictionary<string, string>();
parameters.Add("goodName1", "asdf");
parameters.Add("goodName2", "qwerty");
string text = "this is my {goodName1} template {goodName2} string";
text = Regex.Replace(text, @"\{(.+?)\}", m => parameters[m.Groups[1].Value]);

#3


Like anything, it depends. If the code is going to be called millions of times every day, then think about performance. If it's a few times a day then go for readability.

喜欢什么,这取决于。如果每天要调用数百万次代码,那么请考虑性能。如果它一天几次,那就去寻求可读性。

I've done some benchmarking between using normal (immutable) strings and StringBuilder. Until you start doing a huge amount in small bit of time, you don't need to worry about it too much.

我在使用普通(不可变)字符串和StringBuilder之间做了一些基准测试。直到你在很短的时间内开始大量工作,你不必太担心它。

#4


My spontaneous solution would look like this:

我的自发解决方案看起来像这样:

string data = "This is a {template1} that is {template2}.";

Dictionary<string, string> replacements = new Dictionary<string, string>(){
    {"{template1}", "car"},
    {"{template2}", "red"},
};

foreach (string key in replacements.Keys)
{
    data = data.Replace(key, replacements[key]);
}
Console.WriteLine(data); // outputs "This is a car that is red."

I have used this kind of template replacements in several real-world projects and have never found it to be a performance issue. Since it's easy to use and understand, I have not seen any reason to change it a lot.

我在几个实际项目中使用过这种模板替换,但从未发现它是性能问题。由于它易于使用和理解,我没有看到任何改变它的理由。

#5


BEWARE of getting bogged down with this type of thinking. Unless this code is running hundreds of time per minute and the template file is several K in size, it is more important to get it done. Do not waste a minute thinking about problems like this. In general, if you are doing a lot with string manipulations, then use a string builder. It even has a Replace method. But, why bother. When you are done, and IF you find that you have a performance problem, use PerfMon and fix the REAL bottlenecks at that time.

请注意这种想法陷入困境。除非此代码每分钟运行数百次,并且模板文件的大小为几K,否则完成此操作更为重要。不要浪费一分钟思考这样的问题。通常,如果您在使用字符串操作方面做了很多工作,那么请使用字符串构建器。它甚至有一个Replace方法。但是,为什么要这么麻烦。完成后,如果发现性能问题,请使用PerfMon并修复当时的REAL瓶颈。

#6


The same thing above that Fredrick posted above, but with linq.

与上面Fredrick发布的相同,但是使用了linq。

    public static string FindandReplace(this string inputText, Dictionary<string, string> placeHolderValues)
    {
        if (!string.IsNullOrEmpty(inputText))
        {
            return placeHolderValues.Keys.Aggregate(inputText, (current, key) => current.Replace(key, placeHolderValues[key]));
        }
        else return inputText;
    }

#7


If you need a good, fast, but simple template engine, you should check out StringTemplate. For simple templates that don't require any logic or flow control in the template itself, StringTemplate is GREAT.

如果你需要一个好的,快速但简单的模板引擎,你应该检查StringTemplate。对于模板本身不需要任何逻辑或流控制的简单模板,StringTemplate是GREAT。

http://www.stringtemplate.org/download.html

#8


The fastest way to do it is with a StringBuilder using individual calls to StringBuilder.Append(), like this:

最快的方法是使用StringBuilder,使用对StringBuilder.Append()的单独调用,如下所示:

string result = new StringBuilder("this is my ")
                 .Append(UserVar1)
                 .Append(" template ")
                 .Append(UserVar2)
                 .Append(" string")
                 .ToString();

I've thoroughly benchmarked the framework code, and this will be fastest. If you want to improve readability you could keep a separate string to show the user, and just use this in the background.

我已经对框架代码进行了彻底的基准测试,这将是最快的。如果您想提高可读性,可以保留一个单独的字符串来显示用户,并在后台使用它。

#9


Just modified the above answer to the following:

刚刚将以上答案修改为以下内容:

    string data = "This is a {template1} that is {template2}.";

    Dictionary<string, string> replacements = new Dictionary<string, string>(){
        {"{template1}", "car"},
        {"{template2}", "red"},
    };

    data.Parse(replacements);

Extension method:

public static class Parser
{
    public static string Parse(this string template, Dictionary<string, string> replacements)
    {
        if (replacements.Count > 0)
        {
            template = replacements.Keys
                        .Aggregate(template, (current, key) => current.Replace(key, replacements[key]));
        }
        return template;
    }
}

Hope this helps.. :)

希望这可以帮助.. :)

#1


From Atwood: It. Just. Doesn't. Matter.

来自阿特伍德:它。只是。不。物。

#2


You can put the parameters in a dictionary and use the Regex.Replace method to replace all of the parameters in one replacement. That way the method scales well if the template string gets long or the number of parameters grows.

您可以将参数放在字典中,并使用Regex.Replace方法替换一个替换中的所有参数。这样,如果模板字符串变长或参数数量增加,该方法可以很好地扩展。

Example:

Dictionary<string, string> parameters = new Dictionary<string, string>();
parameters.Add("goodName1", "asdf");
parameters.Add("goodName2", "qwerty");
string text = "this is my {goodName1} template {goodName2} string";
text = Regex.Replace(text, @"\{(.+?)\}", m => parameters[m.Groups[1].Value]);

#3


Like anything, it depends. If the code is going to be called millions of times every day, then think about performance. If it's a few times a day then go for readability.

喜欢什么,这取决于。如果每天要调用数百万次代码,那么请考虑性能。如果它一天几次,那就去寻求可读性。

I've done some benchmarking between using normal (immutable) strings and StringBuilder. Until you start doing a huge amount in small bit of time, you don't need to worry about it too much.

我在使用普通(不可变)字符串和StringBuilder之间做了一些基准测试。直到你在很短的时间内开始大量工作,你不必太担心它。

#4


My spontaneous solution would look like this:

我的自发解决方案看起来像这样:

string data = "This is a {template1} that is {template2}.";

Dictionary<string, string> replacements = new Dictionary<string, string>(){
    {"{template1}", "car"},
    {"{template2}", "red"},
};

foreach (string key in replacements.Keys)
{
    data = data.Replace(key, replacements[key]);
}
Console.WriteLine(data); // outputs "This is a car that is red."

I have used this kind of template replacements in several real-world projects and have never found it to be a performance issue. Since it's easy to use and understand, I have not seen any reason to change it a lot.

我在几个实际项目中使用过这种模板替换,但从未发现它是性能问题。由于它易于使用和理解,我没有看到任何改变它的理由。

#5


BEWARE of getting bogged down with this type of thinking. Unless this code is running hundreds of time per minute and the template file is several K in size, it is more important to get it done. Do not waste a minute thinking about problems like this. In general, if you are doing a lot with string manipulations, then use a string builder. It even has a Replace method. But, why bother. When you are done, and IF you find that you have a performance problem, use PerfMon and fix the REAL bottlenecks at that time.

请注意这种想法陷入困境。除非此代码每分钟运行数百次,并且模板文件的大小为几K,否则完成此操作更为重要。不要浪费一分钟思考这样的问题。通常,如果您在使用字符串操作方面做了很多工作,那么请使用字符串构建器。它甚至有一个Replace方法。但是,为什么要这么麻烦。完成后,如果发现性能问题,请使用PerfMon并修复当时的REAL瓶颈。

#6


The same thing above that Fredrick posted above, but with linq.

与上面Fredrick发布的相同,但是使用了linq。

    public static string FindandReplace(this string inputText, Dictionary<string, string> placeHolderValues)
    {
        if (!string.IsNullOrEmpty(inputText))
        {
            return placeHolderValues.Keys.Aggregate(inputText, (current, key) => current.Replace(key, placeHolderValues[key]));
        }
        else return inputText;
    }

#7


If you need a good, fast, but simple template engine, you should check out StringTemplate. For simple templates that don't require any logic or flow control in the template itself, StringTemplate is GREAT.

如果你需要一个好的,快速但简单的模板引擎,你应该检查StringTemplate。对于模板本身不需要任何逻辑或流控制的简单模板,StringTemplate是GREAT。

http://www.stringtemplate.org/download.html

#8


The fastest way to do it is with a StringBuilder using individual calls to StringBuilder.Append(), like this:

最快的方法是使用StringBuilder,使用对StringBuilder.Append()的单独调用,如下所示:

string result = new StringBuilder("this is my ")
                 .Append(UserVar1)
                 .Append(" template ")
                 .Append(UserVar2)
                 .Append(" string")
                 .ToString();

I've thoroughly benchmarked the framework code, and this will be fastest. If you want to improve readability you could keep a separate string to show the user, and just use this in the background.

我已经对框架代码进行了彻底的基准测试,这将是最快的。如果您想提高可读性,可以保留一个单独的字符串来显示用户,并在后台使用它。

#9


Just modified the above answer to the following:

刚刚将以上答案修改为以下内容:

    string data = "This is a {template1} that is {template2}.";

    Dictionary<string, string> replacements = new Dictionary<string, string>(){
        {"{template1}", "car"},
        {"{template2}", "red"},
    };

    data.Parse(replacements);

Extension method:

public static class Parser
{
    public static string Parse(this string template, Dictionary<string, string> replacements)
    {
        if (replacements.Count > 0)
        {
            template = replacements.Keys
                        .Aggregate(template, (current, key) => current.Replace(key, replacements[key]));
        }
        return template;
    }
}

Hope this helps.. :)

希望这可以帮助.. :)