我可以使用LINQ更优雅地重写它吗?

我有一个double[][] ,我想转换为CSV字符串格式(即一行中的每一行,以逗号分隔的行元素)。 我这样写的:

 public static string ToCSV(double[][] array) { return String.Join(Environment.NewLine, Array.ConvertAll(array, row => String.Join(",", Array.ConvertAll(row, x => x.ToString()))); } 

有没有更优雅的方式来使用LINQ写这个?

(我知道,可以使用临时变量来使这看起来更好,但这种代码格式更能传达我想要的东西。)

这与double任何嵌套序列兼容。 它还将ToString实现推迟到调用者,允许格式化,同时避免混乱的IFormatProvider重载:

 public static string Join(this IEnumerable source, string separator) { return String.Join(separator, source.ToArray()); } public static string ToCsv(this IEnumerable rows, Func valueToString) where TRow : IEnumerable { return rows .Select(row => row.Select(valueToString).Join(", ")) .Join(Environment.NewLine); } 

你可以,但我不会亲自做所有的行 – 我会使用迭代器块:

 public static IEnumerable ToCSV(IEnumerable source) { return source.Select(row => string.Join(",", Array.ConvertAll(row, x=>x.ToString()))); } 

这将返回每一行(调用者可以有效地使用WriteLine等,而不会缓冲所有内容)。 它现在也可以从double[]行的任何来源调用(包括但不限于锯齿状数组)。

另外 – 使用局部变量,您可以使用StringBuilder使每一行稍微便宜一些。


要一次返回整个字符串,我会优化它以使用单个StringBuilder进行所有字符串工作; 多一点啰嗦,但效率更高(中间字符串少得多):

 public static string ToCSV(IEnumerable source) { StringBuilder sb = new StringBuilder(); foreach(var row in source) { if (row.Length > 0) { sb.Append(row[0]); for (int i = 1; i < row.Length; i++) { sb.Append(',').Append(row[i]); } } } return sb.ToString(); } 

您也可以使用Aggregate

 public static string ToCSV(double[][] array) { return array.Aggregate(string.Empty, (multiLineStr, arrayDouble) => multiLineStr + System.Environment.NewLine + arrayDouble.Aggregate(string.Empty, (str, dbl) => str + "," + dbl.ToString())); } 

你可以用LINQ做到这一点,但我不确定你是否比你更喜欢这个。 我怕你没有。 🙂

 var q = String.Join(Environment.NewLine, (from a in d select String.Join(", ", (from b in a select b.ToString()).ToArray())).ToArray()); 

干杯,马蒂亚斯