108

I have the following

data.AppendFormat("{0},",dataToAppend);

The problem with this is that I am using it in a loop and there will be a trailing comma. What is the best way to remove the trailing comma?

Do I have to change data to a string and then substring it?

4

12 回答 12

253

最简单和最有效的方法是执行此命令:

data.Length--;

通过这样做,您将指针(即最后一个索引)移回一个字符,但您不会更改对象的可变性。事实上,清除 aStringBuilder也是最好的Length(但Clear()为了清晰起见,实际上使用该方法,因为这就是它的实现的样子):

data.Length = 0;

再次,因为它不会更改分配表。想想就好像说,我不想再识别这些字节了。现在,即使在调用 时ToString(),它也不会识别过去的任何东西Length,好吧,它不能。它是一个可变对象,它分配的空间比你提供的空间多,它就是这样构建的。

于 2013-06-20T13:40:25.880 回答
48

只需使用

string.Join(",", yourCollection)

这样你就不需要StringBuilderand 循环了。




关于异步案例的长篇补充。截至 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在这里您可以找到一个可编译的示例。

于 2013-06-20T13:38:02.973 回答
13

在循环之后使用以下内容。

.TrimEnd(',')

或者干脆改成

string commaSeparatedList = input.Aggregate((a, x) => a + ", " + x)
于 2013-06-20T13:37:01.323 回答
12

这个怎么样..

string str = "The quick brown fox jumps over the lazy dog,";
StringBuilder sb = new StringBuilder(str);
sb.Remove(str.Length - 1, 1);
于 2013-06-20T13:41:31.633 回答
7

我更喜欢操纵字符串生成器的长度:

data.Length = data.Length - 1;
于 2013-06-20T13:43:51.027 回答
3

您应该使用该string.Join方法将项目集合转换为逗号分隔的字符串。它将确保没有前导或尾随逗号,并确保有效地构造字符串(没有不必要的中间字符串)。

于 2013-06-20T13:38:19.240 回答
3

我建议,你改变你的循环算法:

  • 不要在项目之后添加逗号,而是在之前添加逗号
  • 使用以 false 开头的布尔变量,不要取消第一个逗号
  • 测试后将此布尔变量设置为true
于 2013-06-20T13:37:37.993 回答
2

你有两个选择。第一个是非常容易使用Remove的方法,它非常有效。第二种方法是使用ToString起始索引和结束索引(MSDN 文档

于 2013-06-20T13:38:44.140 回答
2

类似的问题在这里。

我喜欢使用 StringBuilder 扩展方法。

RemoveLast 方法

于 2013-06-20T13:38:57.720 回答
2

是的,一旦循环完成,将其转换为字符串:

String str = data.ToString().TrimEnd(',');
于 2013-06-20T13:37:30.017 回答
1

最简单的方法是使用 Join() 方法:

public static void Trail()
{
    var list = new List<string> { "lala", "lulu", "lele" };
    var data = string.Join(",", list);
}

如果您确实需要 StringBuilder,请在循环后修剪结束逗号:

data.ToString().TrimEnd(',');
于 2013-06-20T13:40:41.467 回答
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

小提琴我

为什么???@ (&**(&@ !!

问题很简单,但我花了一段时间才弄清楚:因为最后还有 2 个不可见字符CRLF(回车和换行)。因此,您需要去掉最后 3 个字符:

var builder = new StringBuilder();
builder.AppendLine("One,");
builder.Length -= 3; // This will work
Console.WriteLine(builder.ToString());

综上所述

使用Length--orLength -= 1如果您调用的最后一个方法是Append. Length =- 3如果您调用了最后一个方法,请使用AppendLine.

于 2020-10-16T21:52:50.700 回答