我有以下代码
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
}
答案 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来获得当前运行的失败计数。
我提出了这个解决方案,表明我们没有锁定现有的预先打包的解决方案。语言和框架为我们提供了很多机会来扩展它以满足我们的需求。