从使用stringbuilder构建的字符串中删除最后一个字符的最佳方法
本文关键字:删除 最后一个 字符 方法 最佳 字符串 stringbuilder 构建 | 更新日期: 2023-09-27 18:19:08
我有以下内容
data.AppendFormat("{0},",dataToAppend);
这样做的问题是我在循环中使用它,并且后面会有一个逗号。去掉末尾逗号的最好方法是什么?
我是否必须将数据更改为字符串,然后将其子字符串?
最简单和最有效的方法是执行以下命令:
data.Length--;
通过这样做,您将指针(即最后一个索引)向后移动一个字符,但您不改变对象的可变性。事实上,清除StringBuilder
最好也用Length
来完成(但实际上要使用Clear()
方法来明确,因为这就是它的实现方式):
data.Length = 0;
还是,因为它不会改变分配表。你可以这样想,我不想再识别这些字节了。现在,即使调用ToString()
,它也不能识别超过Length
的任何东西,嗯,它不能。它是一个可变对象,分配的空间比你提供的要多,它就是这样构建的
就用
string.Join(",", yourCollection)
这样你就不需要StringBuilder
和循环了。
关于异步大小写的长补充。截至2019年,当数据异步传入时,这不是一个罕见的设置。
如果你的数据是异步收集,没有string.Join
过载占用IAsyncEnumerable<T>
。但是手动创建一个很容易,从string.Join
:
public static class StringEx
{
public static async Task<string> JoinAsync<T>(string separator, IAsyncEnumerable<T> seq)
{
if (seq == null)
throw new ArgumentNullException(nameof(seq));
await using (var en = seq.GetAsyncEnumerator())
{
if (!await en.MoveNextAsync())
return string.Empty;
string firstString = en.Current?.ToString();
if (!await en.MoveNextAsync())
return firstString ?? string.Empty;
// Null separator and values are handled by the StringBuilder
var sb = new StringBuilder(256);
sb.Append(firstString);
do
{
var currentValue = en.Current;
sb.Append(separator);
if (currentValue != null)
sb.Append(currentValue);
}
while (await en.MoveNextAsync());
return sb.ToString();
}
}
}
如果数据是异步来的,但是不支持接口IAsyncEnumerable<T>
(就像在注释SqlDataReader
中提到的那样),将数据包装到IAsyncEnumerable<T>
中相对容易:
async IAsyncEnumerable<(object first, object second, object product)> ExtractData(
SqlDataReader reader)
{
while (await reader.ReadAsync())
yield return (reader[0], reader[1], reader[2]);
}
并使用:
Task<string> Stringify(SqlDataReader reader) =>
StringEx.JoinAsync(
", ",
ExtractData(reader).Select(x => $"{x.first} * {x.second} = {x.product}"));
为了使用Select
,你需要使用nuget包System.Interactive.Async
。您可以在这里找到一个可编译的示例。
这个怎么样?
string str = "The quick brown fox jumps over the lazy dog,";
StringBuilder sb = new StringBuilder(str);
sb.Remove(str.Length - 1, 1);
在循环后使用以下代码。
.TrimEnd(',')
或者直接改成
string commaSeparatedList = input.Aggregate((a, x) => a + ", " + x)
我更喜欢操作stringbuilder的长度:
data.Length = data.Length - 1;
找到了!
如果你像下面这样使用AppendLine
,这个线程上的大多数答案将不起作用:
var builder = new StringBuilder();
builder.AppendLine("One,");
builder.Length--; // Won't work
Console.Write(builder.ToString());
builder = new StringBuilder();
builder.AppendLine("One,");
builder.Length += -1; // Won't work
Console.Write(builder.ToString());
builder = new StringBuilder();
builder.AppendLine("One,");
Console.Write(builder.TrimEnd(',')); // Won't work
小提琴我
为什么? ? @ (和* *(和@ ! !
这个问题很简单,但花了我一段时间才弄清楚:因为在CR
和LF
(回车和换行)的末尾有2个不可见的字符。因此,您需要去掉最后3个字符:
var builder = new StringBuilder();
builder.AppendLine("One,");
builder.Length -= 3; // This will work
Console.WriteLine(builder.ToString());
在结论如果最后调用的方法是Append
,则使用Length--
或Length -= 1
。如果您上次调用的方法是AppendLine
,则使用Length =- 3
我建议你改变你的循环算法:
- 在 前加逗号,而不是项目后
- 使用以false开头的布尔变量,不使用第一个逗号
- 测试后将布尔变量设置为true
您应该使用string.Join
方法将项目集合转换为逗号分隔的字符串。它将确保没有前后逗号,并确保字符串被有效地构造(没有不必要的中间字符串)。
最简单的方法是使用Join()方法:
public static void Trail()
{
var list = new List<string> { "lala", "lulu", "lele" };
var data = string.Join(",", list);
}
如果您确实需要StringBuilder,请在循环后删除结束逗号:
data.ToString().TrimEnd(',');
是的,在循环完成后将其转换为字符串:
String str = data.ToString().TrimEnd(',');
您有两个选择。第一个是非常容易使用的Remove
方法,它是相当有效的。第二种方法是使用ToString
与开始索引和结束索引(MSDN文档)
这里也有类似的问题
我喜欢使用StringBuilder扩展方法。
RemoveLast方法
将stringbuilder的长度缩短1;
StringBuilder sb = new StringBuilder();
sb.Length--;
我知道这不是有效的方式,因为它转换成sb = sb-1;
备选有效方案
sb.Remove(starting_index, how_many_character_to_delete);
在我们的例子中是
sb.Remove(sb.length-1,1)