lambda表达式foreach循环

时间:2012-09-08 01:39:45

标签: c# .net lambda

我有以下代码

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    
}

3 个答案:

答案 0 :(得分:6)

使用LINQ:

int someCount = intarr.Count(val => val % 2 == 0);

答案 1 :(得分:3)

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

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

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

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

答案 2 :(得分:0)

没有(太多)阻止你滚动自己的Where计算失败。 “没什么” 因为lambda和带有yield return语句的方法都不允许引用/ ref参数,所以带有以下签名的所需扩展名将无效

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

但是,我们可以为failure-count声明一个局部变量,并返回一个可以获取失败计数的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来获得当前运行的失败计数。

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