C#函数式编程之序列

过了许久的时间,终于趁闲暇的时间来继续将函数式编程这个专辑连载下去,这段时间开头是为IOS这个新方向做准备,将OC的教程写成了SWIFT版,当然我个人是支持Xamarin,但是我一般会先掌握原生态的开发,再掌握Xamarin。后面剩下的时间开发了一个Xamarin App项目,用了十几天完成的。今天的内容将对比较简单,就是讲述如何利用函数式编程来实现列表推导。说的简单点就是列表的数据并不像我们平时开发那样实现写好的,而是通过一定的算法计算出来的(不是程序一打开就计算完成的,而是在使用的时候才计算的,并且只计算到我们使用的那一项为止)。

用函数方法实现迭代器

首先我们当然是先编写一个高阶函数来实现列表推导的主要功能部分,具体的代码如下所示:

 1         public static IEnumerable<T> Sequence<T>(Func<T, T> getNext, T startVal, Func<T, bool> endReached)
2 {
3 if (getNext == null)
4 yield break;
5 yield return startVal;
6 T val = startVal;
7 while (endReached == null || !endReached(val))
8 {
9 val = getNext(val);
10 yield return val;
11 }
12 }

这个函数的作用就是根据一定的算法进行迭代,而这里利用了C# 2.0才有的语法。该函数首先是根据startVal开始迭代,并且根据getNext计算下一个值,而endReached则用来约束结束条件。所以我们可以看到如果endReached为NULL也是可行的,这样这个序列就是无穷的,当然不是死循环。下面我们利用一段简单的代码来掩饰如何使用这个函数:

        static void Main(string[] args)
{
var oddNumbersForm1 = Sequence<int>(x => x + 2, 1, x => x >= 20);
foreach (int x in oddNumbersForm1)
{
Console.WriteLine(x);
}
Console.ReadKey();
}

最后我们在命令行界面中可以看到如下的显示:

值域

很多时候我们使用的序列都是很简单的,而利用上面的Sqquence函数则会变得复杂,同时这个函数还无法实现一些我们需要的功能,比如需要判断一个值时候存在范围中等等,所以我们下面将利用一个简单的Range来实现这些功能,当然内部还是使用的如上的Sequence函数,下面是具体的代码:

 1         public class Range<T> : IEnumerable<T>
2 {
3 private T start;
4 private T end;
5 private Comparison<T> compare;
6 private IEnumerable<T> sequence;
7
8 private static int Compare<U>(U one,U other)
9 {
10 return Comparer<U>.Default.Compare(one,other);
11 }
12
13 public Range(T start, T end, Func<T, T> getNext, Comparison<T> compare)
14 {
15 this.start = start;
16 this.end = end;
17 this.compare = compare;
18 this.sequence = Sequence<T>(getNext, start, v => compare(getNext(v), end) > 0);
19 }
20
21 public Range(T start, T end, Func<T, T> getNext)
22 : this(start, end, getNext, Compare) { }
23
24 public IEnumerator<T> GetEnumerator()
25 {
26 return sequence.GetEnumerator();
27 }
28
29 System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
30 {
31 return ((IEnumerable<T>)this).GetEnumerator();
32 }
33
34 public bool Contains(T value)
35 {
36 return compare(value, start) >= 0 && compare(end, value) >= 0;
37 }
38 }

通过上面的代码我们可以看到Range的功能远远比Sequence函数要强大的多,并且我们可以看到我们还提供了Contains方法用来判断指定的值是否在值域中,另外我们还可以获得IEnumerable借口的各种扩展方法供我们使用。

限制

有时我们的迭代器的实现可能很复杂,如果还要加上限制不仅仅会影响到其性能,同时还会导致代码的可读性较差,所以我们可以将这两者进行分离,负责生成序列的函数只需要没有任何限制,而将限制移转到外部,比如函数TFunc是一个返回序列的函数,并且没有限制,而CFunc则接受一个最大值,以及用来计算序列的函数,并且返回负责条件的序列,那么我们就可以像如下这样循环获取值:

1 foreach(int x in CFunc(10,TFunc)){
2 Console.WriteLine(x);
3 }

至此关于函数式编程中的序列就结束了,后面的时间笔者将会抓紧时间尽快将这个专辑结束掉,开始集中在Xamarin.Android这个系列的教程上。

在满足必要的经济的条件下,研究更加高深的技术.满足自己的野心

C#函数式编程-序列的更多相关文章

  1. C#函数式编程之序列

    过了许久的时间,终于趁闲暇的时间来继续将函数式编程这个专辑连载下去,这段时间开头是为IOS这个新方向做准备,将OC的教程写成了SWIFT版,当然我个人是支持Xamarin,但是我一般会先掌握原生态的开 ...

  2. python基础-函数式编程

    python基础-函数式编程  高阶函数:map , reduce ,filter,sorted 匿名函数:  lambda  1.1函数式编程 面向过程编程:我们通过把大段代码拆成函数,通过一层一层 ...

  3. Reactor事件驱动的两种设计实现:面向对象 VS 函数式编程

    Reactor事件驱动的两种设计实现:面向对象 VS 函数式编程 这里的函数式编程的设计以muduo为例进行对比说明: Reactor实现架构对比 面向对象的设计类图如下: 函数式编程以muduo为例 ...

  4. python【6】-函数式编程

    一.高阶函数 map,reduce 1.map() 函数接收两个参数,一个是函数,一个是序列,map将传入的函数依次作用到序列的每个元素,并把结果作为新的list返回. def f(x): retur ...

  5. Atitit 函数式编程与命令式编程的区别attilax总结  qbf

    Atitit 函数式编程与命令式编程的区别attilax总结  qbf 1.1. 函数式程序就是一个表达式.命令式程序就是一个冯诺依曼机的指令序列. 命令式编程是面向计算机硬件的抽象,有变量(对应着存 ...

  6. Python 函数式编程 & Python中的高阶函数map reduce filter 和sorted

    1. 函数式编程 1)概念 函数式编程是一种编程模型,他将计算机运算看做是数学中函数的计算,并且避免了状态以及变量的概念.wiki 我们知道,对象是面向对象的第一型,那么函数式编程也是一样,函数是函数 ...

  7. Python入门笔记(21):Python函数(4):关于函数式编程的内建函数

    一.关于函数式编程的内建函数 apply()逐渐被舍弃,这里不讨论 1.filter() #filter(func,seq) """纯Python描述filter函数&q ...

  8. Python基础:函数式编程

    一.概述 Python是一门多范式的编程语言,它同时支持过程式.面向对象和函数式的编程范式.因此,在Python中提供了很多符合 函数式编程 风格的特性和工具. 以下是对 Python中的函数式编程 ...

  9. 简明python教程 --C++程序员的视角(九):函数式编程、特殊类方法、测试及其他

    函数式编程 Lambda exec,eval和assert语句,repr函数   lambda语句 用来创建简短的单行匿名函数 print_assign = lambda name, value: n ...

随机推荐

  1. PLSQL Developer下报错信息显示乱码问题

    PLSQL Developer下报错信息显示乱码问题 连接环境:win 7 数据库版本号:oracle 11g 模拟一个错误,查看错误提示显示"????"乱码问题,例如以下: 检查 ...

  2. js的StringBuffer实施和使用类

    <strong>JAVA有一个StringBuffer分类,js但不是在下面,以实现自己的简单js的StringBuffer分类.</strong> //创建一个StringB ...

  3. 初学者应学会如何加快seo

    新手学习如何加快seo 介绍: 应该如何初学者学习SEO,前弯路.真正的高手SEO知识. 作为一个新人,学习如何加快seo知识吧?        多人天天都在学习seo知识.看别人的文章.看多了就感觉 ...

  4. [译]MVC应用程序生命周期

    原文:MVC Application Lifecycle 来一探究竟在MVC应用程序中参与请求处理的各个不同组件. 目录: 序言 背景 UrlRoutingModule RouteHandler Mv ...

  5. HDU 1272 小希迷宫(并检查集合)

    意甲冠军:被判处无向图无环和连接无处不在 思考:并检查集合,trap 您可能有一个直接输入0 0 并且....合并的时候按某一个方向会爆栈,爆了好几次...下次考虑一下直接递归找祖先吧 #includ ...

  6. 【J2SE】java实现简单照片查看器

    程序执行结果: project结构图: 程序代码: import java.awt.BorderLayout; import java.awt.FileDialog; import java.awt. ...

  7. C++ STL它vector详细解释

    Vectors    vector它是C++标准模板库部分,它是一种多用途,你可以使用各种数据结构和算法的模板类和库. vector其原因被认为是一个容器.因为它可以被存储为各种类型的对象作为容器.一 ...

  8. C#值传递和按引用传递

    知识点: 值类型和引用类型  为值类型,,据        对于引用类型来说,栈中存储的是堆中对象的地址 值传递和引用传递 对于值传递,传递的是栈中保存的数据        对于引用传递.传递的是栈本 ...

  9. 《神秘的程序员们》漫画26~28:《万年坑系列》 I、II、III(转)

    26 <万年坑系列> I:那些令你憎恶的系统从何而来? 世界上总有一些令人憎恶的系统,而你却天天非用不可.这些系统的提供方们既不缺钱也不缺人,有的还很热衷于改版升级. 但为何升级完后,它们 ...

  10. Java8 Lambda表达应用 -- 单线程游戏server+异步数据库操作

    前段时间我们游戏server升级到开发环境Java8,这些天,我再次server的线程模型再次设计了一下,耗费Lambda表情. LambdaJava代码.特别是丑陋不堪的匿名内部类,这篇文章主要就是 ...