Joh*_*ens 6 c# linq performance split list
我试图使用LINQ将List拆分为两个列表,而不是两次迭代'master'列表.一个List应包含LINQ条件为true的元素,另一个应包含所有其他元素.这是可能吗?
现在我只使用两个LINQ查询,因此两次迭代(巨大的)主列表.
这是我现在使用的(伪)代码:
List<EventModel> events = GetAllEvents();
List<EventModel> openEvents = events.Where(e => e.Closer_User_ID == null);
List<EventModel> closedEvents = events.Where(e => e.Closer_User_ID != null);
Run Code Online (Sandbox Code Playgroud)
是否可以在不重复原始List两次的情况下产生相同的结果?
小智 9
您可以使用ToLookup扩展方法如下:
List<Foo> items = new List<Foo> { new Foo { Name="A",Condition=true},new Foo { Name = "B", Condition = true },new Foo { Name = "C", Condition = false } };
var lookupItems = items.ToLookup(item => item.Condition);
var lstTrueItems = lookupItems[true];
var lstFalseItems = lookupItems[false];
Run Code Online (Sandbox Code Playgroud)
GroupBy并且Single应该完成你正在寻找的东西:
var groups = events.GroupBy(e => e.Closer_User_ID == null).ToList(); // As others mentioned this needs to be materialized to prevent `events` from being iterated twice.
var openEvents = groups.SingleOrDefault(grp => grp.Key == true)?.ToList() ?? new List<EventModel>();
var closedEvents = groups.SingleOrDefault(grp => grp.Key == false)?.ToList() ?? new List<EventModel>();
Run Code Online (Sandbox Code Playgroud)
您可以通过将其转换为查找表来在一个语句中执行此操作:
var splitTables = events.Tolookup(event => event.Closer_User_ID == null);
Run Code Online (Sandbox Code Playgroud)
这将返回一个由两个元素组成的序列,其中每个元素都是一个IGrouping<bool, EventModel>. 该Key说的顺序是否与空Closer_User_Id,或者不是序列。
然而,这看起来相当神秘。我的建议是使用新函数扩展 LINQ。
此函数采用任何类型的序列,以及将序列分为两组的谓词:与谓词匹配的组和与谓词不匹配的组。
这样您就可以使用该函数将各种IEnumerable序列分成两个序列。
请参阅揭开扩展方法的神秘面纱
public static IEnumerable<IGrouping<bool, TSource>> Split<TSource>(
this IEnumerable<TSource> source,
Func<TSource,bool> predicate)
{
return source.ToLookup(item => item.Condition);
}
Run Code Online (Sandbox Code Playgroud)
用法:
IEnumerable<Person> persons = ...
// divide the persons into adults and non-adults:
var result = persons.Split(person => person.IsAdult);
Run Code Online (Sandbox Code Playgroud)
Result 有两个元素:一个 Key 为 true 的元素包含所有 Adults。
虽然用法现在变得更容易阅读,但您仍然存在处理完整序列的问题,而实际上您可能只想使用其中的几个结果项
让我们返回 an IEnumerable<KeyValuePair<bool, TSource>>,其中布尔值指示项目匹配还是不匹配:
public static IEnumerable<KeyValuePair<bool, TSource>> Audit<TSource>(
this IEnumerable<TSource> source,
Func<TSource,bool> predicate)
{
foreach (var sourceItem in source)
{
yield return new KeyValuePair<bool, TSource>(predicate(sourceItem, sourceItem));
}
}
Run Code Online (Sandbox Code Playgroud)
现在你得到一个序列,其中每个元素都说明它是否匹配。如果您只需要其中的几个,则不会处理序列的其余部分:
IEnumerable<EventModel> eventModels = ...
EventModel firstOpenEvent = eventModels.Audit(event => event.Closer_User_ID == null)
.Where(splitEvent => splitEvent.Key)
.FirstOrDefault();
Run Code Online (Sandbox Code Playgroud)
where 说你只想要那些通过审计的审计项目(关键是真的)。
因为您只需要第一个元素,所以不再审计序列的其余部分
| 归档时间: |
|
| 查看次数: |
623 次 |
| 最近记录: |