【问题标题】:lambda expression foreach looplambda 表达式 foreach 循环
【发布时间】:2012-09-08 13:28:20
【问题描述】:

我有以下代码

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    
}

【问题讨论】:

  • 为什么将其限制为 lambda 解决方案?
  • 我是 Lambda 表达式的新手,所以不适合简明扼要地表达我的意图。

标签: c# .net lambda


【解决方案1】:

使用 LINQ:

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

【讨论】:

    【解决方案2】:

    我绝对更喜欢 @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

    【讨论】:

      【解决方案3】:

      没有什么(太多)可以阻止您滚动自己的 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&lt;int&gt;,并且局部变量对于从 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&lt;&gt; 的情况下过早地跳出循环,因此失败计数只会反映遇到的失败,而不是像 @nneonneo 的解决方案(我更喜欢)中的失败总数。 /em> 另外,如果 LINQ 的 Where 扩展的实现更改为每个项目多次调用谓词,那么失败计数将不正确。另一个有趣的地方是,在您的循环体内,您应该能够调用 getFailureCount Func 以获取目前正在运行的失败计数。

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

      【讨论】:

      • 感谢您的努力。我真的很感激。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-12-07
      • 2018-02-20
      • 2016-08-07
      相关资源
      最近更新 更多