对空序列使用Enumerable.Agregate(..)方法
本文关键字:Agregate 方法 Enumerable | 更新日期: 2023-09-27 17:59:24
我想使用Enumerable.Agregate(…)方法来连接由分号分隔的字符串列表。相当容易,不是吗?
考虑以下因素:
private const string LISTSEPARATOR = "; ";
-
相册有序轨道是
List<TrackDetails>
- TrackDetails具有DiscNumberInt16?财产
如果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语句中执行此操作?
提前谢谢。
若要连接字符串列表,请使用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
)
此重载允许您指定种子值。如果指定了种子值,则在集合为空时也会将其用作结果。
编辑:如果你真的想使用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()
我认为您可能会发现以下helper扩展方法很有用。
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));
这仍然读作"从上到下",这大大有助于可读性。
您可以使用
.Aggregate(string.Empty, (i, j) => i + LISTSEPARATOR + j);
对于初始值,它适用于空集合
像这样使用String.Join
:
txtDiscNumber.Text = String.Join(LISTSEPARATOR,
album.OrderedTracks
.Where(a => a.DiscNumber.HasValue)
.Select(a => a.DiscNumber.Value.ToString())
.Distinct());
为了调试目的,经常使用这样的方法,提出了两种扩展方法:
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);