Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/linq/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# Enumerable.Count()的替代项==n_C#_Linq_Count_Enumerable - Fatal编程技术网

C# Enumerable.Count()的替代项==n

C# Enumerable.Count()的替代项==n,c#,linq,count,enumerable,C#,Linq,Count,Enumerable,我正在为Enumerable.Count()==n寻找更好的替代方案。我能想到的最好的办法是: static class EnumerableExtensions { public static bool CountEquals<T>(this IEnumerable<T> items, int n) { if (n <= 0) throw new ArgumentOutOfRangeException("n"); // use An

我正在为
Enumerable.Count()==n
寻找更好的替代方案。我能想到的最好的办法是:

static class EnumerableExtensions
{
    public static bool CountEquals<T>(this IEnumerable<T> items, int n)
    {
        if (n <= 0) throw new ArgumentOutOfRangeException("n"); // use Any()

        var iCollection = items as System.Collections.ICollection;
        if (iCollection != null)
            return iCollection.Count == n;

        int count = 0;
        bool? retval = null;
        foreach (var item in items)
        {
            count++;

            if (retval.HasValue)
                return false;

            if (count == n)
                retval = true;
        }

        if (retval.HasValue)
            return retval.Value;

        return false;
    }
}

class Program
{
    static void Main(string[] args)
    {
        var items0 = new List<int>();
        var items1 = new List<int>() { 314 };
        var items3 = new List<int>() { 1, 2, 3 };
        var items5 = new List<int>() { 1, 2, 3, 4, 5 };
        var items10 = Enumerable.Range(0, 10);
        var itemsLarge = Enumerable.Range(0, Int32.MaxValue);

        Console.WriteLine(items0.CountEquals(3));
        Console.WriteLine(items1.CountEquals(3));
        Console.WriteLine(items3.CountEquals(3));
        Console.WriteLine(items5.CountEquals(3));
        Console.WriteLine(itemsLarge.CountEquals(3));
    }
}
静态类EnumerableExtensions
{
公共静态布尔CountEquals(此IEnumerable items,int n)
{

如果(n使用
Enumerable.Count
会比上面的代码好得多。它已经在内部为
ICollection
进行了优化

也就是说,如果您必须保留扩展,您可以稍微简化循环:

int count = 0;
foreach (var item in items)
{
    count++;
    if(count > n)
        return false;
}
return count == n;

您可以结合使用
Take
Count
来完全消除循环:

public static bool CountEquals<T>(this IEnumerable<T> items, int n)
{
  var iCollection = items as System.Collections.ICollection;
  if (iCollection != null)
    return iCollection.Count == n;
  return items.Take(n + 1).Count() == n;
}
public static bool CountEquals(此IEnumerable items,int n)
{
var iCollection=作为System.Collections.iCollection的项目;
如果(iCollection!=null)
返回iCollection.Count==n;
返回项目。获取(n+1)。计数()==n;
}

你所说的“更好”到底是什么意思?更快?更容易

从本质上讲,您似乎已经编写了一个专门的方法,该方法针对一个特定的任务进行了优化。您提到了对其进行泛化,但它的性能优势来自于它如此具体的事实(假设有性能优势——像
Count
这样的方法已经很难进行性能调优了,而且编译器在优化这样的东西方面也很在行)

如果此特定操作的性能非常重要,值得替换二十个字符的表达式
xyz.Count()==abc
有几十行代码,您可能想尝试其他提高性能的方法,如重构。在大多数情况下,使用托管代码的开销将使您获得的性能奖金(如果有的话)相形见绌

也就是说,如果你有大约1000万件物品,而你的目标数量要少得多,我很确定下面的内容会缩短迭代的时间:

int count = 0;
var subset = items.TakeWhile(x => count++ < n + 1);
return count == n + 1;
int count=0;
var子集=items.TakeWhile(x=>count++

易于阅读,易于维护,速度可能也一样快。

您意识到
可枚举.Count
已经将
列表
(实际上是任何
集合
)作为特例进行处理,并使用(var e=items.GetEnumerator()){for(int i=0;iCount
属性,对吗如果(!e.MoveNext())返回false;返回!e.MoveNext();}@Dan:True-但是,如果您的“n”很小,我个人会使用
集合。Take(n+1).Count()==n
退出短路…@Reed丑陋但可以工作:尝试{l.ElementAt(n)}catch(ArgumentOutOfRangeException ex){@Magnus:这是可行的,但我尽量避免对流控制使用异常处理。@Magnus只确认序列长度的下限为
n
,而不是上限。值得一试。我仍然认为编译器可能能够优化
xyz.Count()==n
,但如果没有,您可以尝试Stephen Cleary的代码。但是,这仍然(有效地)在Take()和Count()中执行循环。是的,循环仍然存在;我发布的内容与Reed的答案(或者Mehrdad的答案,真的)相当。