我有一个IGroupings序列
IEnumerable<IGrouping<Key, Element>> sequence = ...;
Run Code Online (Sandbox Code Playgroud)
和一个谓词
Func<Element, bool> predicate = ...;
Run Code Online (Sandbox Code Playgroud)
如何Element通过保持结果 an来过滤sIEnumerable<IGrouping<Key, Element>>而不使序列变平并重新创建完全重新创建分组?
我可以做类似的事情
IEnumerable<IGrouping<Key, Element>> filtered =
from grouping in sequence
from element in grouping
where predicate(element)
select new { grouping.Key, element } into keyElem
group keyElem.element by keyElem.Key into g
select g;
Run Code Online (Sandbox Code Playgroud)
但是,根据序列的大小和所涉及的类型,这需要一些时间和/或内存。
我想“简单地”过滤IGroupings 中的元素。我会在结果中接受空分组。
(我认为这个问题可以通过回答 how to filter the elements of anIEnumerable<IEnumerable<Element>>同时保持结果 an的问题来回答IEnumerable<IEnumerable<Element>>。)
您不能修改现有的IGrouping,但您可以轻松创建自己的实现和辅助方法:
public static class Groupings
{
public static IGrouping<TKey, TElement>
FilterElements<TKey, TElement>(
this IGrouping<TKey, TElement> grouping,
Func<TElement, bool> predicate) =>
new LateGrouping<TKey, TElement>(grouping.Key, grouping.Where(predicate));
}
internal class LateGrouping<TKey, TElement> : IGrouping<TKey, TElement>
{
public TKey Key { get; }
private readonly IEnumerable<TElement> elements;
public LateGrouping(TKey key, IEnumerable<TElement> elements)
{
Key = key;
this.elements = elements;
}
public IEnumerator<TElement> GetEnumerator() => elements.GetEnumerator();
IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();
}
Run Code Online (Sandbox Code Playgroud)
然后你就可以拿你的IEnumerable<IGrouping<...>>并使用一个普通的选择,在里面过滤:
groupings = groupings.Select(g => g.FilterElements(predicate));
Run Code Online (Sandbox Code Playgroud)