Linq下的函数式编程初探
接触c#又好几年了,感觉整个c#功能确实很强大,基本上你能想到的事情都能帮你完成,但同时过于庞大的框架也给人很大的压力。
这么多年使用c#的经验告诉我,能用c#的东西就尽量用,这样既可以提高编程效率,又可以减少程序的错误。
Linq是c#3.5添加进来的新特性,也是c#里面我最喜欢的编程框架之一,我现在基本上很多时候都在用Linq在编程,今天就来谈谈一些本人对于使用Linq进行函数式编程的体会。
Linq是啥东西就不用多介绍了,关于函数式编程,网上也有很多介绍的资料,我感觉函数式编程和c#这类命令式编程最大的不同就是:
函数式编程是对问题本身的表述,而命令式编程则是对问题解决过程的描述
不知道我的感觉大家同不同意,下面就来一段示例说明一下,这是一个同学问我的问题,他说他用c弄了好几个晚上都没弄好(哈哈,我这个同学不是计算机专业的,所以可以理解哈):
问题描述:
八个数 1 4 3 25 26 25 28 29 分成两组,具体算法:
算出平均值=X
标准差=s
ga=X-s
gb=X+s
da[i]=abs(x[i]-ga)
db[i]=abs(x[i]-gb)
比较da[i]和db[i]
若da[i]<db[i] 则x[i]分到a组
大于则分到b组
过程还算是比较复杂吧,如果用传统的方法,就是一堆的for循环什么的,我看了之后觉得用Linq来写会方便很多,于是用10分钟写完了下面的代码:
1 static void Main(string[] args) 2 { 3 var arr = new int[] {1,4 ,3, 25, 26, 25 ,28, 29 }; 4 var x = arr.Average(); 5 var s = Math.Sqrt(arr.Select(a=>a-x).Select(b => b*b).Average()); 6 var ga = x - s; 7 var gb = x + s; 8 var da = arr.Select(i => Math.Abs(i - ga)); 9 var db = arr.Select(i => Math.Abs(i - gb)); 10 var group = Enumerable.Range(0, arr.Length).GroupBy(i => da.ElementAt(i) < db.ElementAt(i)); 11 foreach (var g in group) 12 { 13 Console.WriteLine("-----------------------------------"); 14 foreach (var e in g) 15 { 16 Console.Write(arr[e] + " "); 17 } 18 Console.WriteLine(); 19 } 20 }
输出结果
加上初始化和结果输出,只有20行,相当简单哈~~~
从代码来看,基本上就是这个算法过程的表述,过程相当清晰,不存在任何逻辑混乱的地方,这就是函数式编程强大的地方!!!可能有人会说这程序的效率怎样,呵呵,这个问题还挺难回答的,不过我这里只是说明函数式编程的便捷性,并没有太多考虑到运行效率。
于是我接着用Linq实现了一个快速排序算法(其实可以直接使用OrderBy的~~)
1 class Program 2 { 3 static void Main(string[] args) 4 { 5 var arr = new byte[200000]; 6 new Random().NextBytes(arr); 7 foreach (var i in QuickSort(arr)) 8 { 9 Console.Write(i + " "); 10 } 11 } 12 static IEnumerable<byte> QuickSort(IEnumerable<byte> arr) 13 { 14 if (arr.Count() <= 1) 15 { 16 return arr; 17 } 18 else 19 { 20 var pivot = arr.First(); 21 return arr.GroupBy(i => i.CompareTo(pivot)) 22 .OrderBy(k=>k.Key) 23 .SelectMany(g => g.Key == 0 ? g : QuickSort(g)); 24 } 25 } 26 }
运行效率还是相当不错的