在不调用ToString()的情况下从StringBuilder
的末尾修剪空格的有效方法是什么。修剪()并返回到新的SB new StringBuilder(sb.ToString().Trim())
。
答案 0 :(得分:37)
以下是扩展方法,因此您可以这样调用它:
sb.TrimEnd();
此外,它返回SB实例,允许您链接其他调用(sb.TrimEnd().AppendLine()
)。
public static StringBuilder TrimEnd(this StringBuilder sb)
{
if (sb == null || sb.Length == 0) return sb;
int i = sb.Length - 1;
for (; i >= 0; i--)
if (!char.IsWhiteSpace(sb[i]))
break;
if (i < sb.Length - 1)
sb.Length = i + 1;
return sb;
}
注意:
1)如果为Null或Empty,则返回。
2)如果实际上不需要Trim,我们正在谈论一个非常快速的返回时间,可能最昂贵的调用是对char.IsWhiteSpace的单次调用。因此,在不需要时调用TrimEnd几乎为零,而不是这些ToString()。Trim()返回SB路径。
3)否则,如果需要修剪,最昂贵的是对char.IsWhiteSpace的多次调用(在第一个非空白字符处中断)。当然,循环向后迭代;如果所有都是空白,你最终会得到一个SB.Length为0。
4)如果遇到空格,则i索引保持在循环之外,这允许我们适当地剪切长度。在StringBuilder中,这是非常高效的,它只是设置一个内部长度整数(内部char []保持相同的内部长度。)
UPDATE2:看看 Ryan Emerle 的优秀笔记如下,这些笔记纠正了我的一些误解(SB的内部工作比我做出的要复杂得多):
StringBuilder在技术上是char []块的链表。所以 我们最终没有留在LOH。调整长度在技术上不是 简单的更改结束索引,因为如果你移动到另一个 必须维护容量,因此可能需要一个新的块 分配。不过,你只在最后设置了Length属性, 所以这似乎是一个很好的解决方案。 Eric Lippert的相关细节:https://stackoverflow.com/a/6524401/62195
另外,请参阅这篇讨论.NET 4.0新StringBuilder实现的好文章:http://1024strongoxen.blogspot.com/2010/02/net-40-stringbuilder-implementation.html
-------更新--------
下面说明当StringBuilder长度被更改时会发生什么(这里对SB执行的唯一真实操作,以及仅在需要时):
StringBuilder sb = new StringBuilder("cool \t \r\n ");
sb.Capacity.Print(); // 16
sb.Length.Print(); // 11
sb.TrimEnd();
sb.Capacity.Print(); // 16
sb.Length.Print(); // 4
在更改Length之后,您可以看到内部数组(m_ChunkChars)保持相同的大小,事实上,您可以在调试器中看到它甚至不会覆盖(在这种情况下为空格)字符。他们是孤儿。
答案 1 :(得分:3)
你可以试试这个:
StringBuilder b = new StringBuilder();
b.Append("some words");
b.Append(" to test ");
int count = 0;
for (int i = b.Length - 1; i >= 0; i--)
{
if (b[i] == ' ')
count++;
else
break;
}
b.Remove(b.Length - count, count);
string result = b.ToString();
只有在有空格然后突破循环时才会遍历结束。
或者甚至喜欢这样:
StringBuilder b = new StringBuilder();
b.Append("some words");
b.Append(" to test ");
do
{
if(char.IsWhiteSpace(b[b.Length - 1]))
{
b.Remove(b.Length - 1,1);
}
}
while(char.IsWhiteSpace(b[b.Length - 1]));
string get = b.ToString();
答案 2 :(得分:0)
public static class StringBuilderExtensions
{
public static StringBuilder Trim(this StringBuilder builder)
{
if (builder.Length == 0)
return builder;
var count = 0;
for (var i = 0; i < builder.Length; i++)
{
if (!char.IsWhiteSpace(builder[i]))
break;
count++;
}
if (count > 0)
{
builder.Remove(0, count);
count = 0;
}
for (var i = builder.Length - 1; i >= 0; i--)
{
if (!char.IsWhiteSpace(builder[i]))
break;
count++;
}
if (count > 0)
builder.Remove(builder.Length - count, count);
return builder;
}
}
答案 3 :(得分:0)
要进行全面修整,在StringBuilder
级别上执行此操作不是明智的/可取的,而是在ToString
时执行此操作,例如使用以下TrimToString
实现:
public static string TrimToString(this StringBuilder sb)
{
if (sb == null) return null;
sb.TrimEnd(); // handles nulle and is very inexpensive, unlike trimstart
if (sb.Length > 0 && char.IsWhiteSpace(sb[0])) {
for (int i = 0; i < sb.Length; i++)
if (!char.IsWhiteSpace(sb[i]))
return sb.ToString(i);
return ""; // shouldn't reach here, bec TrimEnd should have caught full whitespace strings, but ...
}
return sb.ToString();
}
答案 4 :(得分:-1)
StringBuilder myString = new StringBuilder("This is Trim test ");
if (myString[myString.Length - 1].ToString() == " ")
{
myString = myString.Remove(myString.Length - 1, 1);
}