嘿,我正试图找出在列表中抓取数据段的最优方法。根据他们的类型假设我在一个列表中有以下数据:
public enum StepStatus {
Skipped,
NotStarted,
Completed,
}
public enum StepType
public class Steps {
StepStatus Status { get; set; }
StepType Type { get; set;}
// Other info
}
我有一个所有步骤及其状态的列表
//Data
1, StepStatus.Skipped, StepType.Notification
2, StepStatus.Completed, StepType.Notification
3, StepStatus.NotStarted, StepType.Notification
4, StepStatus.NotStarted, StepType.Notification
5, StepStatus.NotStarted, StepType.Approval}
6, StepStatus.NotStarted, StepType.Notification
我想抓取所有未启动的通知,直到并包括第一次批准。所以我想返回列表的这段
3, StepStatus.NotStarted, StepType.Notification
4, StepStatus.NotStarted, StepType.Notification
5, StepStatus.NotStarted, StepType.Approval
我能想到的最简单的方法是。
var firstApprovalStep = steps.FirstOrDefault(x => x.Status == StepStatus.NotStarted && x.Type == StepType.Approval);
if(null == firstApprovalStep)
{
//If there are no pending approvals left return the pending notfications
return steps.Reverse().TakeWhile(x => x.Status == StepStatus.NotStarted && x.Type == StepType.Notification);
}
//Find the element in the list with that index and grab all prior.
steps.GetNotStartedNotificationsPrior(firstStep);
我想知道是否有一种更简单/更聪明的方法来使用linq抓取这个段?
既然我们知道你使用的是List<T>
,我们可以稍微作弊,使用源IEnumerable
两次而不会受到太大的惩罚。
这是一个扩展方法:
public static IEnumerable<T> TakePast<T>(this IEnumerable<T> items, Func<T, bool> posFn) => items.Take(items.TakeWhile(i => !posFn(i)).Count()+1);
你可以这样做:
return steps.Where(s => s.StepStatus == StepStatus.NotStarted)
.TakePast(s => s.StepType == StepType.Approval);
当然,这意味着你可以展开扩展方法:
return steps.Where(s => s.StepStatus == StepStatus.NotStarted)
.Take(steps.Where(s => s.StepStatus == StepStatus.NotStarted).TakeWhile(s => s.StepType != StepType.Approval)).Count()+1);
我假设唯一的StepType
s是Notification
和Approval
,因为您没有定义enum
。
下面是枚举任何序列一次的泛型实现:
public static IEnumerable<T> TakePast<T>(this IEnumerable<T> items, Func<T, bool> posFn) {
var ie = items.GetEnumerator();
while (ie.MoveNext()) {
yield return ie.Current;
if (posFn(ie.Current))
yield break;
}
}