C# 当可枚举项在Linq中的元素数超过X时提前返回

C# 当可枚举项在Linq中的元素数超过X时提前返回,c#,linq,C#,Linq,Linq中最有效的写作方式是什么: 返回可枚举的.Count()>x 我至少在寻找一个解决方案: 不涉及计算整个可枚举项 最好是标准的.NET Linq 应该在不同的提供者上工作 请注意,enumerable.Any()在0以上的情况下工作得非常好,但我正在寻找一种解决方案,可以检查x以上的值 示例: 考虑一个非常大的可枚举项,它是使用生成并返回的 Linq中最出色(最美丽)的写作方式是什么: 返回可枚举的.Count()>x 这有什么不对呢 return enumerable.Count(

Linq中最有效的写作方式是什么:

返回可枚举的.Count()>x

我至少在寻找一个解决方案:

  • 不涉及计算整个可枚举项
  • 最好是标准的.NET Linq
  • 应该在不同的提供者上工作
请注意,
enumerable.Any()
在0以上的情况下工作得非常好,但我正在寻找一种解决方案,可以检查
x
以上的值

示例:

考虑一个非常大的可枚举项,它是使用
生成并返回

Linq中最出色(最美丽)的写作方式是什么:
返回可枚举的.Count()>x

这有什么不对呢

return enumerable.Count() > x;
?

如果
enumerable
的实际类型也实现了
ICollection
,那么它将只返回
ICollection.Count
,这通常是一个O(1)运算。对于
IQueryable
,大多数查询提供程序都会将其转换为
SELECT COUNT(*)FROM…
,这大约是您可以获得的最快速度


因此,只有相对较少的边缘情况比
Count
更好;可能很少有人会尝试为它们编写代码,这会适得其反。

我认为您需要这样的东西:

public static bool LazyCount<T>(this IEnumerable<T> source, int count)
{
    var enumerator = source.GetEnumerator();

    int i = 0;

    while(enumerator.MoveNext())
    {
        i++;
        if(i > count) return true;
    }
    return false;
}

注意:我非常不擅长命名,但你应该明白,你可以随意修改它。

如果你只想使用LINQ,我会使用

enumerable.Take(x).Count() == x
尽管我更喜欢Selman22方法

那么简单呢:

return enumerable.Skip(x).Any();

我想这就是你要找的。

如果你想知道你是否有超过5个,你可以做以下事情


enumerable.Take(6).Count()==6

没有内置的LINQ方法可以提供最有效的解决方案。基本上,您需要检查
IEnumerable
是否有Count属性(通过
ICollection
),如果没有,则枚举它

public static class MoreEnumerable
{
    public static bool HasAtLeast<T>(this IEnumerable<T> source, int count)
    {
        if (source is ICollection<T>)
        {
            return ((ICollection<T>)source).Count > count;
        }
        else if (source is ICollection)
        {
            return ((ICollection)source).Count > count;
        }

        return source.Skip(count).Any();
    }
}
公共静态类更多可枚举
{
公共静态布尔值至少为(此IEnumerable源,int计数)
{
if(源为ICollection)
{
返回((ICollection)源)。计数>计数;
}
else if(源为ICollection)
{
返回((ICollection)源)。计数>计数;
}
返回source.Skip(count).Any();
}
}

euh。为什么投反对票?请看以下答案:嗨,哈比卜,谢谢你的回答。在这种特殊情况下(其他查询无法访问的属性),将对其进行计算。Any()对于大于0的对象非常有效。但是如何做大于
x
?返回enumerable.Count()>x有什么问题,我不确定是否还有其他方法可以做到这一点。关于简单的
跳过
任何
?F.e:
返回enumarble.Skip(x).Any()?这将枚举
Count()
不会枚举的集合。这一点很好。因此,如果您真的想让它在所有情况下都能正常运行,这意味着您需要首先进行自定义检查,如果它是IList。。。因此,我猜您是朝着编写自己的扩展方法的方向走的?@DirkBoer从技术上讲,您可以检查
ICollection
,因为
Count
就是在这里定义的,但是是的。请注意,正是这样做的。:)@DirkBoer是的,最有效的标准用例解决方案是检查
ICollection
,并首先使用Count属性进行比较,因为它通常是O(1)。查看我的答案。除了它仍然会枚举非查询上下文中的所有对象,@DStanley:)我感觉mike z的答案将是最接近的。您可以使用Take或Skip@LuisFilipe没错,主体可以使用Take或Skip,但重要的一点是,如果您首先检查
ICollection
,性能会更好。这确实是一个理论问题,而不是一个实际问题,但我添加了一个适当的示例。也就是说,一种非常大的
收益率
方法。
public static class MoreEnumerable
{
    public static bool HasAtLeast<T>(this IEnumerable<T> source, int count)
    {
        if (source is ICollection<T>)
        {
            return ((ICollection<T>)source).Count > count;
        }
        else if (source is ICollection)
        {
            return ((ICollection)source).Count > count;
        }

        return source.Skip(count).Any();
    }
}