我想使用 Enumerable.Aggregate(...)方法来连接由分号分隔的字符串列表。相当容易,不是吗?
考虑以下因素:
private const string LISTSEPARATOR = "; ";
List<TrackDetails>
如果 Distinct()返回的序列为空(由于 Aggregate()方法不适用于空序列),以下语句将抛出异常:
txtDiscNumber.Text = album.OrderedTracks
.Where(a => a.DiscNumber.HasValue)
.Select(a => a.DiscNumber.Value.ToString())
.Distinct()
.Aggregate((i, j) => i + LISTSEPARATOR + j);
我正在使用的解决方法:
List<string> DiscNumbers =
album.OrderedTracks
.Where(a => a.DiscNumber.HasValue)
.Select(a => a.DiscNumber.Value.ToString())
.Distinct()
.ToList();
if (!DiscNumbers.Any())
txtDiscNumber.Text = null;
else
txtDiscNumber.Text =
DiscNumbers.Aggregate((i, j) => i + LISTSEPARATOR + j);
有没有更好的解决方案?是否可以在单个LINQ语句中执行此操作?
提前致谢。
答案 0 :(得分:36)
要连接字符串列表,请使用string.Join
方法。
Aggregate
函数不适用于空集合。它需要一个二进制累加函数,它需要集合中的一个项作为种子值传递给二元函数。
但是,有一个overload of Aggregate
:
public static TResult Aggregate<TSource, TAccumulate, TResult>(
this IEnumerable<TSource> source,
TAccumulate seed,
Func<TAccumulate, TSource, TAccumulate> func,
Func<TAccumulate, TResult> resultSelector
)
此重载允许您指定种子值。如果指定了种子值,则如果该集合为空,它也将用作结果。
编辑:如果您真的想使用Aggregate
,可以这样做:
sequence.Aggregate(string.Empty, (x, y) => x == string.Empty ? y : x + Separator + y)
或者通过这种方式使用StringBuilder
:
sequence.Aggregate(new StringBuilder(), (sb, x) => (sb.Length == 0 ? sb : sb.Append(Separator)).Append(x)).ToString()
答案 1 :(得分:8)
我认为您可能会发现以下帮助程序扩展方法很有用。
public static TOut Pipe<TIn, TOut>(this TIn _this, Func<TIn, TOut> func)
{
return func(_this);
}
它允许您以下列方式表达您的查询。
txtDiscNumber.Text = album.OrderedTracks
.Where(a => a.DiscNumber.HasValue)
.Select(a => a.DiscNumber.Value.ToString())
.Distinct()
.Pipe(items => string.Join(LISTSEPARATOR, items));
这仍然是“从上到下”,这极大地有助于提高可读性。
答案 2 :(得分:5)
像这样使用String.Join
:
txtDiscNumber.Text = String.Join(LISTSEPARATOR,
album.OrderedTracks
.Where(a => a.DiscNumber.HasValue)
.Select(a => a.DiscNumber.Value.ToString())
.Distinct());
答案 3 :(得分:2)
您可以使用
.Aggregate(string.Empty, (i, j) => i + LISTSEPARATOR + j);
具有初始值,适用于空集合
答案 4 :(得分:0)
用于调试的很多方法, 提出了两种扩展方法:
public static string Concatenate<T, U>(this IEnumerable<T> source, Func<T, U> selector, string separator = ", ")
{
if (source == null)
{
return string.Empty;
}
return source
.Select(selector)
.Concatenate(separator);
}
public static string Concatenate<T>(this IEnumerable<T> source, string separator = ", ")
{
if (source == null)
{
return string.Empty;
}
StringBuilder sb = new StringBuilder();
bool firstPass = true;
foreach (string item in source.Distinct().Select(x => x.ToString()))
{
if (firstPass)
{
firstPass = false;
}
else
{
sb.Append(separator);
}
sb.Append(item);
}
return sb.ToString();
}
像这样使用:
string myLine = myCol.Concatenate(x => x.TheProperty);