c# - 使用 LINQ 有效地验证累积和验证属性
问题描述
我想验证我的列表中元素的总和(非负数)是否低于某些值。而且我不想计算没有必要的整个总和。(如果我们证明第一个元素的总和不尊重该属性,我们将停止计算)
所以我想要一个 LINQ 命令来验证累积和的每个元素是否低于某个值,只要它看到不等式成立。
var b = a.Aggregate(new List<int> { 0 }, (ls, x) => { ls.Add(x + ls.Last()); return ls; }).All(x => x < 4);
这种方法行不通。当它看到累积和的第 i 个元素不满足属性但整个累积和是计算时,所有的都停止。
你有更好的方法吗?(我知道我们可以用循环有效地做到这一点,但我想用 LINQ 做到这一点)
如果我使用循环:
var s = 0;
var b = true;
foreach(var x in list)
{
s=s+x;
if(s>4){ b= false; break;}
}
谢谢
解决方案
你不需要使用 LINQ 方法来做你想做的事。您可以使用枚举器和循环编写自己的代码。毕竟,LINQ-to-Objects 操作本身是使用循环实现的。例如TakeWhile被实现为一个迭代器,它遍历源并产生匹配的元素:
static IEnumerable<TSource> TakeWhileIterator<TSource>(IEnumerable<TSource> source, Func<TSource, int, bool> predicate) {
int index = -1;
foreach (TSource element in source) {
checked { index++; }
if (!predicate(element, index)) break;
yield return element;
}
}
缺点是这会为迭代器生成一个状态机并返回所有匹配的元素,无论它们是否被使用。
您可以编写自己的扩展方法,计算循环中的总和,并true
在循环完成但未达到限制时返回:
public static bool SumBelow(this IEnumerable<int> source, int limit)
{
int sum=0;
foreach (var element in source)
{
sum+=element;
if (sum>limit)
{
return false;
}
}
return true;
}
并将其用作扩展方法:
var isSumBelow = someEnumerable.SumBelow(5);
为什么不是通用方法?
无法指定运算符约束或 IAddable 接口,这就是Sum()本身为每种类型分别实现的原因,例如:
public static int Sum(this IEnumerable<int> source) {
if (source == null) throw Error.ArgumentNull("source");
int sum = 0;
checked {
foreach (int v in source) sum += v;
}
return sum;
}
功能性方式
将累加器和条件检查器作为函数传递可用于创建一种通用的、可重用的方法,该方法可以处理任何转换和条件:
public static bool AccWithinLimit<T>(
this IEnumerable<T> source,
Func<T,T,T> accumulator,
Func<T,bool> terminator,
T seed=default)
{
T total=seed;
foreach (var element in source)
{
total = accumulator(element,total);
if (terminator(total))
{
return false;
}
}
return true;
}
这可用于检查整数数组的部分和:
var myArray=new []{1,2,3};
var limit = 5;
var totalBelowLimit = myArray.AccWithinLimit(myArray,
(sum,elm)=>sum+elm,
sum=>sum>limit);
或带有双打列表的部分产品:
var myList = new List<double>{1.0, 2.0, 3.0};
var limit = 10;
var totalBelowLimit = myList.AccWithinLimit(myArray,
(sum,elm)=>sum*elm,
sum=>sum>limit,
1);
推荐阅读
- webpack - 为什么“webpack”项无法识别为 cmdlet、函数
- java - Java:存储字符串集的最佳数据结构,而不是逐个字符地重新散列
- javascript - 读取 JSON 文件
- android - 使用 Regex 获取 JSON 的一部分
- javascript - 如何从 Vue 应用程序的处理函数访问单击的元素引用?
- single-sign-on - CAS - 根据用户输入的用户名使用不同的身份验证处理程序
- reactjs - Redux-typescript ,如何正确键入映射到道具的状态?
- c++ - 从多个 c++ QThreads 调用 c 函数
- sql - SQL连接到表中的多行
- position - 如何在 Hololens 上获得手的位置?