只要字符串不死,每次操作都会导致GC加载,即使是StringBuilder插入/删除调用。 我会通过插入点剪切源字符串,然后用需要插入的数据“压缩”它。 之后,您可以将列表中的字符串串起来,以获得结果字符串。
下面是一个示例代码,做拆分/压缩操作。 它假定字段被定义为(位置,长度,值)的简化。
public class Field
{
public int pos { get; set; }
public int len { get; set; }
public string value { get; set; }
public string tag { get; set; }
}
class Program
{
static void Main(string[] args)
{
var source = "You'r order price [price] and qty [qty].";
var fields = new List<Field>();
fields.Add(new Field()
{
pos = 18,
len = 7,
value = "15.99$",
tag = "price"
});
fields.Add(new Field()
{
pos = 37-3,
len = 5,
value = "7",
tag = "qty"
});
Console.WriteLine(Zip(Split(source, fields), fields));
Console.WriteLine(ReplaceRegex(source, fields));
}
static IEnumerable<string> Split(string source, IEnumerable<Field> fields)
{
var index = 0;
foreach (var field in fields.OrderBy(q => q.pos))
{
yield return source.Substring(index, field.pos - index);
index = field.pos + field.len;
}
yield return source.Substring(index, source.Length - index);
}
static string Zip(IEnumerable<string> splitted, IEnumerable<Field> fields)
{
var items = splitted.Zip(fields, (l, r) => new string[] { l, r.value }).SelectMany(q => q).ToList();
items.Add(splitted.Last());
return string.Concat(items);
}
static string ReplaceRegex(string source, IEnumerable<Field> fields)
{
var fieldsDict = fields.ToDictionary(q => q.tag);
var re = new Regex(@"\[(\w+)\]");
return re.Replace(source, new MatchEvaluator((m) => fieldsDict[m.Groups[1].Value].value));
}
}
顺便说一句,最好是使用正则表达式替换特殊的用户标记,如[price],[qty]?
“*由于我将这么做很多次,我希望它尽可能快*”。定义'很多'?每个按钮点击几千次?那么这是过早的优化。夜间批量工作每小时几百万次?此外,还有一些不成熟的优化(每小时以约278次/秒的速度运行一个小时)。如果这个字符串操作变成瓶颈,我会惊呆了。 – 2010-08-11 14:49:23
是的,但如果可能的话,编写高效的代码仍然很不错。我只是检查我没有做可怕的低效率事情。作为一名.NET开发人员,您总是会听到有关错误的字符串操作会如何影响性能的问题。 该计划的核心实际上将用于多个项目。第一个涉及文件转换。输出文件包含基于输入文件生成的值。我相信每个输入文件可能包含数百个(如果不是数千个)记录。但使用此代码的未来应用程序可能会有更重的工作负载。 – James 2010-08-11 15:16:12
在将字段附加到流中时,您可能会更好,而不是构建字符串并编写它。使用'System.IO.StringWriter',你总是可以得到输出为一个字符串,如果你需要它出于任何原因。 – 2010-08-11 15:26:10