c# – 如何以功能方式获取中间总和列表?使用LINQ?
给定一个对象列表,我需要返回一个列表,该列表包含对象和目前为止所见列表中所有对象的对象属性的总和.
更一般地给出 var input = new int[] {1,2,3} 我想有输出 // does not compile but did not want to include extra classes. var output = { (1,1),(2,3),(3,6) }; 这种“正确”的功能方式是什么?我当然可以用标准的迭代方法来实现它,但我正在寻找如何以功能性,懒惰的方式完成它. 谢谢 解决方法
在功能方面,这是以下组合:
压缩 取两个序列并创建一系列元素元组 和 地图 取一个函数f和一个序列,并为原始序列中的每个x返回一个新的序列f(x) 拉链是trivial in c# 4.0 static class Enumerable { public static IEnumerable<TResult> Zip<TFirst,TSecond,TResult>( this IEnumerable<TFirst> first,IEnumerable<TSecond> second,Func<TFirst,TResult> func) { var ie1 = first.GetEnumerator(); var ie2 = second.GetEnumerator(); while (ie1.MoveNext() && ie2.MoveNext()) yield return func(ie1.Current,ie2.Current); } } 然后我们需要地图.我们已经拥有它,这就是我们在c#中所谓的Select IEnumerable<int> input = { 1,3,4 }; int a = 0; var accumulate = input.Select(x => { a += x; return a; }); 但是把它加入到它自己的方法中更安全(在c#中没有讨论)并??允许支持任意类型/累积. static class Enumerable { public static IEnumerable<T> SelectAccumulate<T>( this IEnumerable<T> seq,Func<T,T,T> accumulator) { var e = seq.GetEnumerator(); T t = default(T); while (e.MoveNext()) { t = accumulator(t,e.Current); yield return t; } } } 然后我们可以把它们放在一起 var input = new int[] {1,3}; var mapsum = input.Zip( input.SelectAccumulate((x,y) => x+y),(a,b) => new {a,b}); 这将迭代序列两次,但更通用.您可以选择在标准选择和简单闭包中自己执行累加器,但它不再像“构建块”那样有用,它是功能编程背后的驱动力之一. 除了一个方法之外,元组支持是一种痛苦,因为匿名类型不会在没有相当麻烦的情况下遍历方法边界. c#4.0中应包含一些基本元组.假设一个名为Pair< T,U>的元组类/结构.你可以这样做: public static IEnumerable<Pair<T,T>> ZipMapAccumulate<T>( this IEnumerable<T> input,T> accumulator) { return input.Zip( input.SelectAccumulate((x,y) => accumulator (x,y)),b) => new Pair<T,T>(a,b)); } //get an int specific one public static Func<IEnumerable<int>,IEnumerable<Pair<int,int>>> ZipMapSum() { return input => Enumerable.ZipMapAccumulate( input,(i,j) => i + j); } 其中c#linq变得比f#更加繁琐是对运算符,currying和元组的不良支持,除非你将所有内容保存在一个函数中并且每次为每种类型“重建它”. (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |