如何用LINQ改写迭代算法避免重复计算?支持MoreLINQ方案
如何用LINQ改写避免重复计算的迭代算法?
现有如下迭代算法,需要用LINQ改写,同时避免重复调用ComplicatedCalculation()方法:
int GetMatchingValue(List<Thing> things) { foreach(Thing t in things) { var value = t.ComplicatedCalculation(); if(value > 0) return value; } return 0; }
直接用FirstOrDefault筛选Thing会导致重复调用计算方法,因此需要调整LINQ写法来避免这个问题。
原生LINQ解决方案(无重复计算)
核心思路是先投影计算结果,再筛选,这样每个Thing只会调用一次ComplicatedCalculation(),且找到第一个符合条件的值后立即停止遍历(短路求值),和原迭代逻辑完全一致:
int GetMatchingValue(List<Thing> things) { // 先投影出所有计算值,再取第一个>0的,无符合项则返回int默认值0 return things.Select(t => t.ComplicatedCalculation()) .FirstOrDefault(v => v > 0); }
如果ComplicatedCalculation()返回的是可空类型(比如int?),可以用空合并运算符兜底:
int GetMatchingValue(List<Thing> things) { return things.Select(t => t.ComplicatedCalculation()) .FirstOrDefault(v => v.HasValue && v.Value > 0) ?? 0; }
原迭代方案的定位
原迭代写法本身已经非常简洁直观,尤其是如果后续需要扩展逻辑(比如同时返回Thing实例和计算值),迭代写法的可读性和灵活性会更强。但如果只是单纯返回符合条件的计算值,上述LINQ写法同样紧凑高效,且代码更具声明式风格。
MoreLINQ实现方案
如果项目中引入了MoreLINQ库,可以利用其FirstOr方法更明确地指定默认值(即使返回类型的默认值不是0也能直接定义):
using MoreLinq; int GetMatchingValue(List<Thing> things) { return things.Select(t => t.ComplicatedCalculation()) .FirstOr(v => v > 0, 0); }
另外,MoreLINQ的TryFirst方法也可以实现类似逻辑,适合需要明确判断是否找到符合项的场景:
using MoreLinq; int GetMatchingValue(List<Thing> things) { if (things.Select(t => t.ComplicatedCalculation()) .TryFirst(v => v > 0, out var result)) { return result; } return 0; }
内容的提问来源于stack exchange,提问作者Mr. Boy
相关产品推荐
相关产品推荐

