lor*_*can 22 c# linq aggregate sequence
我想使用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);
Run Code Online (Sandbox Code Playgroud)
我正在使用的解决方法:
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);
Run Code Online (Sandbox Code Playgroud)
有没有更好的解决方案?是否可以在单个LINQ语句中执行此操作?
提前致谢.
Tom*_*rek 37
要连接字符串列表,请使用该string.Join方法.
该Aggregate函数不适用于空集合.它需要二进制累加函数,它需要集合中的项目作为种子值传递给二元函数.
但是,有一个重载Aggregate:
public static TResult Aggregate<TSource, TAccumulate, TResult>(
this IEnumerable<TSource> source,
TAccumulate seed,
Func<TAccumulate, TSource, TAccumulate> func,
Func<TAccumulate, TResult> resultSelector
)
Run Code Online (Sandbox Code Playgroud)
此重载允许您指定种子值.如果指定了种子值,则在集合为空时也将其用作结果.
编辑:如果你真的想使用Aggregate,你可以这样做:
sequence.Aggregate(string.Empty, (x, y) => x == string.Empty ? y : x + Separator + y)
Run Code Online (Sandbox Code Playgroud)
或者通过这种方式使用StringBuilder:
sequence.Aggregate(new StringBuilder(), (sb, x) => (sb.Length == 0 ? sb : sb.Append(Separator)).Append(x)).ToString()
Run Code Online (Sandbox Code Playgroud)
我想你可能会发现以下帮助扩展方法很有用.
public static TOut Pipe<TIn, TOut>(this TIn _this, Func<TIn, TOut> func)
{
return func(_this);
}
Run Code Online (Sandbox Code Playgroud)
它允许您以下列方式表达您的查询.
txtDiscNumber.Text = album.OrderedTracks
.Where(a => a.DiscNumber.HasValue)
.Select(a => a.DiscNumber.Value.ToString())
.Distinct()
.Pipe(items => string.Join(LISTSEPARATOR, items));
Run Code Online (Sandbox Code Playgroud)
这仍然是"从上到下",这极大地有助于提高可读性.
您可以使用
.Aggregate(string.Empty, (acc, name) => acc + (acc.Length > 0 ? separator : string.Empty) + name)
Run Code Online (Sandbox Code Playgroud)
初始值适用于空集合,但长度检查不太好
使用String.Join这样:
txtDiscNumber.Text = String.Join(LISTSEPARATOR,
album.OrderedTracks
.Where(a => a.DiscNumber.HasValue)
.Select(a => a.DiscNumber.Value.ToString())
.Distinct());
Run Code Online (Sandbox Code Playgroud)