如何将非字符串数组进行String.Join操作的最佳方法?

5

在第二个示例中,将非字符串数组连接成字符串的简写方式是什么?

string[] names = { "Joe", "Roger", "John" };
Console.WriteLine("the names are {0}", String.Join(", ", names)); //ok

decimal[] prices = { 39.99M, 29.99m, 29.99m, 19.99m, 49.99m };
Console.WriteLine("the prices are {0}", String.Join(", ", prices)); //bad overload
5个回答

13

如果您使用LINQ

decimal[] prices = { 39.99M, 29.99m, 29.99m, 19.99m, 49.99m }; 
Console.WriteLine("the prices are {0}", 
    String.Join(", ", 
       prices.Select(p => p.ToString()).ToArray()
    )
);

7
请注意,如果您不使用.NET 4,您需要调用ToArray()函数。 - Jon Skeet
我会点赞,但这会创建第二个数组,对于给出的简单示例来说还好,但在现实世界中这是一个不好的习惯。 - Binary Worrier
2
如果您正在使用.NET 4,您根本不需要LINQ。string.Join(", ", prices); - Marc

5
Console.WriteLine("the prices are {0}", String.Join(", ", Array.ConvertAll(prices, p => p.ToString()));

2
我有两个“分隔符”函数,它们可以帮助我实现这一功能。
它们的占用内存很小,不需要创建第二个数组,在返回字符串时,使用了StringBuilder来优化,因此不会导致不断拼接同一字符串而导致延迟。
因此,它们非常适用于长度非常大和/或未知的系列。
第一个函数将写入TextWriter并不返回任何内容,第二个函数将返回一个字符串,并代理到第一个函数中,传递一个StringWriter。
public static void Delimit<T>(this IEnumerable<T> me, System.IO.TextWriter writer, string delimiter)
{
    var iter = me.GetEnumerator();
    if (iter.MoveNext())
        writer.Write(iter.Current.ToString());

    while (iter.MoveNext())
    {
        writer.Write(delimiter);
        writer.Write(iter.Current.ToString());
    }
}

public static string Delimit<T>(this IEnumerable<T> me, string delimiter)
{
    var writer = new System.IO.StringWriter();
    me.Delimit(writer, delimiter);
    return writer.ToString();
}

所以根据以上价格,您将拥有:
decimal[] prices = { 39.99M, 29.99m, 29.99m, 19.99m, 49.99m }; 
Console.WriteLine("the prices are {0}", prices.Delimit(", "));

或者

decimal[] prices = { 39.99M, 29.99m, 29.99m, 19.99m, 49.99m }; 
Console.Write("the prices are ")
prices.Delimit(System.Console.Out, ", ");
Console.WriteLine();

创建StringWriter与创建Array相比,有很多额外的开销吗?我有一个类似的函数用于创建分隔字符串,它添加文本限定符以创建CSV文件。 - cjk
CK:对于小数组,可能不需要(唯一确定的方法是对它们进行分析)。问题在于非常大的数组或未知大小的序列。此外,如果您有一个十进制值列表,您会首先在列表上调用.ToArray吗?在某个时刻,您的容器需要被复制到一个数组中才能使.Join工作。对我来说,Linq的乐趣在于我可以停止思考不同的集合类型及其包含的内容,只需编写具有最小开销的通用代码即可。 - Binary Worrier

1
ck离开的地方继续,将其提取到一个方法中以使其可重用:
public static class EnumerableExtensions {
  public static string Join<T>(this IEnumerable<T> self, string separator) { 
    if (self == null) throw new ArgumentNullException();
    if (separator == null) throw new ArgumentNullException("separator");
    return String.Join(separator, self.Select(e => e.ToString()).ToArray());
  }
}

现在使用起来更易读:

Console.WriteLine("the prices are {0}", prices.Join(", "));

1
不要在扩展方法中验证“this”时抛出“NullReferenceException”。 - Igal Tabachnik

0

可以使用 LINQ 将其转换为字符串:

Console.WriteLine("the prices are {0}", String.Join(", ", prices.Select(p => p.ToString()).ToArray()));

或者使用Aggregate()代替string.Join()

Console.WriteLine("the prices are {0}",
    prices.Select(p => p.ToString()).
          .Aggregate((total, p) => total + ", " + p));

或者甚至(格式略有不同)

Console.WriteLine(
    prices.Select(p => p.ToString()).
          .Aggregate("the prices are", (total, p) => total + ", " + p));

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接