如何在.NET中通过索引有效地覆盖字符串的一部分?
在我的 .NET 程序中,我允许用户定义“字段”,它们是由业务逻辑计算的值。这些字段具有位置和长度,因此它们都可以插入到给定索引处的单个输出字符串中。我还允许用户指定此输出字符串的默认内容。如果没有定义字段来替换给定位置,则会输出默认字符
我的问题是,如何才能有效地做到这一点? StringBuilder 类有一个 Insert(int index, string value) 方法,但这每次都会延长输出字符串而不是覆盖它。我是否必须使用 StringBuilder[int index] 索引器一次设置每个字符一个,这样效率低吗?因为我会多次这样做,所以我希望它尽可能快。
谢谢。
In my .NET program I allow a user to define "fields" which are values calculated by the business logic. These fields have a position and length, so that they can all be inserted into a single output string at a given index. I also allow a user to specify default content of this output string. If no field is defined to replace a given position, the default character is output instead
My question is, how can I do this efficiently? The StringBuilder class has an Insert(int index, string value) method, but this lengthens the output string each time rather than overwriting it. Am I going to have to set each char one at a time using the StringBuilder[int index] indexer, and is this inefficient? Since I am going to be doing this a lot of times I would like it to be as fast as possible.
Thanks.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(7)
一次只做一个角色可能是你最好的选择。我这样说是因为在
StringBuilder
上调用Insert
和Remove
会导致字符向右/向左移动,就像任何可变的类似方法一样索引集合,例如List
。也就是说,这是一个很好的候选扩展方法,可以让你的生活更轻松一些。
使用示例:
输出:
Doing it one character at a time is likely your best bet. I say this because calling
Insert
andRemove
on aStringBuilder
results in characters being shifted right/left, just as the analogous methods would in any mutable indexed collection such as aList<char>
.That said, this is an excellent candidate for an extension method to make your life a bit easier.
Usage example:
Output:
StringBuilder
类允许您构建可变字符串。在执行插入
之前尝试使用Remove
函数。由于它是随机访问的,所以速度应该非常快。只要StringBuilder
保持相同的容量,就不会花费时间在内存中复制字符串。如果您知道字符串会变长,请尝试在调用New StringBuilder()
时将容量设置得更大The
StringBuilder
class lets you build a mutable string. Try using theRemove
function before doing theInsert
. Since its randomly accessible, it should be very quick. As long as theStringBuilder
keeps the same capacity, it won't be taking time copying strings around in memory. If you know the string will become longer, try setting the capacity to be larger when you callNew StringBuilder()
只要字符串是不可变的,每次对其进行操作都会导致 GC 负载,甚至 StringBuilder 插入/删除调用。
我会通过插入点剪切源字符串,然后用需要插入的数据“压缩”它。
之后,您可以在列表中连接字符串,以获得结果字符串。
这是执行拆分/压缩操作的示例代码。
它假设字段被定义为(位置、长度、值)的元组。
顺便说一句,最好使用正则表达式替换特殊用户标记,例如 [价格]、[数量]?
As long, as strings are immuteble, each manipulation with it, will cause GC load, even StringBuilder insert/remove calls.
I would cut source string by insertion points, and then "zip" it with data, that need to be inserted.
After that you can just concat strings inside list, to get resulting string.
Here is a sample code that do split/zip operaions.
It assumes, that Fields are defined as touple of (position, length, value).
BTW, would be better to replace special user markers, like [price], [qty] using regex?
我建议使用 StringBuilder 类。不过,您可以使用字符串来完成此操作,但可能会产生副作用。这里有几篇博客文章展示了如何操作字符串以及可能的副作用。
http://philosopherdeveloper.wordpress.com /2010/05/28/are-strings-really-immutable-in-net/
http://philosopherdeveloper.wordpress.com/2010/06/13/string-manipulation-in-net-epilogue-plus-new-theme/
I would recommend using the
StringBuilder
class. However you can do it with a string but there can be side effects. Here are a couple blog posts that show how to manipulate strings and the possible side effects.http://philosopherdeveloper.wordpress.com/2010/05/28/are-strings-really-immutable-in-net/
http://philosopherdeveloper.wordpress.com/2010/06/13/string-manipulation-in-net-epilogue-plus-new-theme/
如果替换子字符串将成为一个大瓶颈,您可能想完全放弃子字符串。相反,请将数据分解为可以独立修改的字符串。如下所示:
这是一个简单的静态示例,但我确信可以使其更加通用,这样如果每个用户定义不同的字段,您就可以处理它。将数据分解为字段后,如果您仍然需要修改字段中的单个字符,至少您不会触及整个数据集。
现在,这可能会将瓶颈推向 OutputDataLine 函数,具体取决于您对数据执行的操作。但如有必要,可以单独处理。
If replacing substrings is going to be a big bottleneck, you may want to ditch the substrings thing altogether. Instead, break up your data into strings that can be independently modified. Something like the following:
That's a simple static example, but I'm sure that could be made more generic so that if every user defines fields differently you could handle it. After breaking your data into fields, if you still need to modify individual characters in the fields at least you're not touching the whole set of data.
Now, this may push the bottle neck to the OutputDataLine function, depending on what you're doing with the data. But that can be handled separately if necessary.
如果您的字符串已经预先格式化为长度,那么 StringBuilder 类
刚刚设置了您的起始索引和计数 = 1,以便您可以替换该特定实例。
您可以做的另一件事是使用 String.Format()。将所有预定义字段转换为索引,这样您就会得到一个类似“This {0} is very {1}”的字符串,然后只需将参数与特定索引进行匹配并执行 String.Format(myString, myParams);
——劳尔
If your string is already pre formated for the length then the StringBuilder class has
just set your start index and count = 1 so you can replace that specific instance.
Another thing you could do is use String.Format(). Convert all your pre defined fields into indexes so you get a string like "This {0} is very {1}" and then just match up the parameters to the specific index and do a String.Format(myString, myParams);
-Raul
正如您公平地说的,StringBuilder 有 Insert 方法,但没有 Overwrite 方法。
所以我为我的项目创建了覆盖扩展方法,见下文。
请注意,如果 StringBuilder 没有足够的空间,它将削减该值。但是,您可以轻松修改它的逻辑。
As you fairly stated, StringBuilder has Insert method but no Overwrite method.
So i have created the Overwrite extension method, see below, for my projects.
Note that it will cut the value if the StringBuilder has not enough room for it. You can easily modify it's logic, however.