如何解决如何懒惰地获得空的团体
我想按boolean
值对对象进行分组,并且无论是否有任何元素,我都需要始终获得两组(一组用于true
,一组用于false
)在其中。
使用GroupBy
的通常方法不起作用,因为它只会生成非空组。以例如此代码:
var list = new List<(string,bool)>();
list.Add(("hello",true));
list.Add(("world",false));
var grouping = list.GroupBy(i => i.Item2);
var allTrue = grouping.Last();
var allFalse = grouping.First();
仅当每个boolean
值中至少有一个元素时,此方法才有效。如果我们删除Add
行之一,或什至都删除,allTrue
和allFalse
将不包含正确的组。如果将两者都删除,则甚至会遇到运行时异常,尝试调用Last()
(“序列不包含任何元素”)。
注意:我想偷懒地这样做。 (不:创建两个空集合,遍历输入,填充集合。)
解决方法
.NET平台不包含生成空IGrouping
的内置方法。没有实现该接口的可公开访问的类,因此我们将不得不手动创建一个:
class EmptyGrouping<TKey,TElement> : IGrouping<TKey,TElement>
{
public TKey Key { get; }
public EmptyGrouping(TKey key) => Key = key;
public IEnumerator<TElement> GetEnumerator()
=> Enumerable.Empty<TElement>().GetEnumerator();
IEnumerator IEnumerable.GetEnumerator()
=> GetEnumerator();
}
为了检查所有必需的分组是否可用,我们将需要一种基于它们的Key
进行比较的方法。以下是针对IGrouping
的简单IEqualityComparer
实现:
public class GroupingComparerByKey<TKey,TElement>
: IEqualityComparer<IGrouping<TKey,TElement>>
{
public bool Equals(IGrouping<TKey,TElement> x,IGrouping<TKey,TElement> y)
=> EqualityComparer<TKey>.Default.Equals(x.Key,y.Key);
public int GetHashCode(IGrouping<TKey,TElement> obj)
=> obj.Key.GetHashCode();
}
有了这个基础架构,我们现在可以创建一个懒惰的LINQ运算符,该运算符将缺少的分组附加到可枚举的对象上。让我们称之为EnsureContains
:
public static IEnumerable<IGrouping<TKey,TElement>> EnsureContains<TKey,TElement>(
this IEnumerable<IGrouping<TKey,TElement>> source,params TKey[] keys)
{
return source
.Union(keys.Select(key => new EmptyGrouping<TKey,TElement>(key)),new GroupingComparerByKey<TKey,TElement>());
}
用法示例:
var groups = list
.GroupBy(i => i.Item2)
.EnsureContains(true,false);
注意:GroupBy
运算符产生的可枚举是惰性的,因此每次使用时都会对其求值。评估此运算符的费用相对较高,因此最好避免对其进行多次评估。
当没有这样的匹配对象时,您可以确保获得空集合:
var list = new List<(string,bool)>();
list.Add(("hello",true));
list.Add(("world",false));
var allTrue = list.Where(x => x.Item2);
var allFalse = list.Where(x => !x.Item2);
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。