C# 如何在超集中查找不在子集中的项

C# 如何在超集中查找不在子集中的项,c#,linq,superset,C#,Linq,Superset,我知道ienumerable上有一个“not”,这要归功于linq,它需要一个集合来反对,但是我担心大的性能,最快的算法是什么 从IEnumerable中删除项目子集的唯一方法是通过超集循环,对于超集中的每个项目,通过子集循环,如果在子集中找到该项目,则从超集中删除该项目 这将给你平均O(n²) 现在,如果有关于这些集合的附加信息(可能一个或两个是列表,或者可能一个或两个序列都已排序),则可以帮助您创建更高性能的解决方案 如果您感兴趣,这里有一个扩展方法,可以实现我刚才描述的功能: public

我知道ienumerable上有一个“not”,这要归功于linq,它需要一个集合来反对,但是我担心大的性能,最快的算法是什么

IEnumerable
中删除项目子集的唯一方法是通过超集循环,对于超集中的每个项目,通过子集循环,如果在子集中找到该项目,则从超集中删除该项目

这将给你平均O(n²)

现在,如果有关于这些集合的附加信息(可能一个或两个是列表,或者可能一个或两个序列都已排序),则可以帮助您创建更高性能的解决方案

如果您感兴趣,这里有一个扩展方法,可以实现我刚才描述的功能:

public static IEnumerable<T> Exclude<T>
    (this IEnumerable<T> source, IEnumerable<T> items)
{
    foreach (T t in source)
        if (!items.Contains(t))
            yield return t;
}
公共静态IEnumerable排除
(此IEnumerable源,IEnumerable项)
{
foreach(源中的T)
如果(!items.Contains(t))
收益率t;
}


无论如何,请使用扩展方法:

生成两个序列的集差


通过将超集转换为哈希表(通常为O(n),您可以获得更好的性能,但随后允许您在固定时间内执行查找)。然后可以枚举子集并检查超集中是否存在每个项。整个操作应该需要O(n)个额外内存和O(n)个时间。

如果可以按顺序迭代集合,则可以通过在锁步中迭代这两个集合来保证O(n)行为(而不是哈希集合所具有的“通常是O(n),但在最坏的情况下可能是O(n²))

例如:

//loop boilerplate
if(itemA < itemB) {
    itemA = a.next();
    continue;
}
if(itemA > itemB) {
    itemB = b.next();
    continue;
}
a.remove(itemA);
//循环样板
如果(项目A<项目B){
itemA=a.next();
继续;
}
如果(项目A>项目B){
itemB=b.next();
继续;
}
a、 删除(a项);

您需要自己添加边界检查和其他样板文件。

好的,假设我可以对包含对象的特定属性进行排序;我如何使用它呢?如果使用哈希集(通常是O(1)来检查包含或添加/删除),这就是O(n),其中n是超集的大小。如果子集较小,最好对其进行迭代,并从超集中删除其中的每个项。除非您尝试删除重复项,否则在这种情况下,如果哈希键选择正确,这将是一个O(1)问题,因为哈希键将负责最初删除重复项。但加载键仍将为O(n)。