1

我有以下代码

int someCount = 0;

for ( int i =0 ; i < intarr.Length;i++ )
{
   if ( intarr[i] % 2 == 0 )
   { 
       someCount++;
       continue;
   }
   // Some other logic for those not satisfying the condition
}

是否可以使用任何 Array.Where 或 Array.SkiplWhile 来实现相同的效果?

foreach(int i in intarr.where(<<condtion>> + increment for failures) )
{
      // Some other logic for those not satisfying the condition    
}
4

3 回答 3

6

使用 LINQ:

int someCount = intarr.Count(val => val % 2 == 0);
于 2012-09-08T01:43:35.137 回答
3

对于简短的语句,我绝对更喜欢 @nneonneo 的方式(并且它使用显式 lambda),但是如果您想构建更精细的查询,可以使用LINQ 查询语法

var count = ( from val in intarr 
    where val % 2 == 0 
    select val ).Count();

显然,当查询可以用单个 lambda 表达式表示时,这可能是一个糟糕的选择,但我发现它在编写更大的查询时很有用。

更多示例:http ://code.msdn.microsoft.com/101-LINQ-Samples-3fb9811b

于 2012-09-08T01:45:10.560 回答
0

没有什么(太多)可以阻止您自己滚动Where失败的次数。“没什么”,因为 lambdas 和带有yield return语句的方法都不允许引用 out/ref 参数,因此具有以下签名的所需扩展将不起作用

// dead-end/bad signature, do not attempt
IEnumerable<T> Where(
    this IEnumerable<T> self,
    Func<T,bool> predicate,
    out int failures)

但是,我们可以为失败计数声明一个局部变量并返回一个Func<int>可以获取失败计数的变量,并且局部变量完全可以从 lambdas 引用。因此,这是一个可能的(经过测试的)实现:

public static class EnumerableExtensions
{
    public static IEnumerable<T> Where<T>(
        this IEnumerable<T> self,
        Func<T,bool> predicate,
        out Func<int> getFailureCount)
    {
        if (self == null) throw new ArgumentNullException("self");
        if (predicate == null) throw new ArgumentNullException("predicate");

        int failures = 0;

        getFailureCount = () => failures;

        return self.Where(i =>
            {
                bool res = predicate(i);
                if (!res)
                {
                    ++failures;
                }
                return res;
            });
    }
}

...这是一些练习它的测试代码:

Func<int> getFailureCount;
int[] items = { 0, 1, 2, 3, 4 };
foreach(int i in items.Where(i => i % 2 == 0, out getFailureCount))
{
    Console.WriteLine(i);
}
Console.WriteLine("Failures = " + getFailureCount());

上述测试,运行时输出:

0
2
4
失败 = 2

有几个警告我觉得有义务警告。由于您可以在没有遍历整个 的情况下过早地跳出循环IEnumerable<>,因此失败计数只会反映遇到的失败,而不是@nneonneo 的解决方案(我更喜欢)中的失败总数。另外,如果 LINQ 的实现Where扩展名被更改为每个项目多次调用谓词的方式,那么失败计数将不正确。另一个有趣的地方是,在您的循环体内,您应该能够调用 getFailureCount Func 以获取目前正在运行的失败计数。

我提出这个解决方案是为了表明我们没有被锁定在现有的预打包解决方案中。语言和框架为我们提供了很多机会来扩展它以满足我们的需求。

于 2012-09-08T05:28:20.420 回答