内容简介:昨天在看C#函数式编程这本书的时候,有一处让我干着急,需求是这样: 给多行文字加上数字列表项。针对这个需求你会如何快捷高效的给每个项目加上数字编号呢? 我看书中是这样实现的,如下代码
一:背景
昨天在看C#函数式编程这本书的时候,有一处让我干着急,需求是这样: 给多行文字加上数字列表项。
针对这个需求你会如何快捷高效的给每个项目加上数字编号呢? 我看书中是这样实现的,如下代码
public class Program { public static void Main(string[] args) { var list = new List<string>() { "cnblogs","csdn","zhihu","oschina" }; var items = list.Zip(Enumerable.Range(1, list.Count + 1), (item, i) => $"{i}. {item}").ToList(); items.ForEach(Console.WriteLine); } } ------------------- output ------------------- 1. cnblogs 2. csdn 3. zhihu 4. oschina Press any key to continue . . .
怎么说呢,需求能实现没有问题,但这里还是累赘了,因使用到了拉链函数Zip 和生成范围的Range,全纠缠到一块,有没有更简单粗暴的方式呢? 其实你只用Select的一个带迭代变量的重载方法就可以搞定,但现实中还是有很多的 程序员 不会使用或者说不知道,所以优化后的代码如下。
var items = list.Select((item, i) => $"{i + 1}. {item}").ToList(); ------------------- output ------------------- 1. cnblogs 2. csdn 3. zhihu 4. oschina Press any key to continue . . .
二:源码探究
相信编码多年的我们无数次的在憎恨foreach没有带上索引,这么普罗大众的需求尽然都没有实现,而 python 这样的语言早就给实现了,为了解决这个不足,我还得需要单独定义一个变量在迭代时即时记录,烦不胜烦,就像下面这样。
var index = 0; foreach (var item in list) { index++; Console.WriteLine(item); }
可能FCL类库程序员也深有体会,所以加了一个可以在迭代中获取当前index的绝妙方法,这么:cow::nose:造福人类的方法却发现身边知道的人少之又少,小遗憾哈。
1. ILSpy查看源码
从下面代码的 SelectIterator 枚举类可以看到,其实在底层也是单独给你定义了一个index,然后逐一回调给你的回调函数,这种封装很有必要,不过全是高阶函数,功底很深哈!
public static IEnumerable<TResult> Select<TSource, TResult>(this IEnumerable<TSource> source, Func<TSource, int, TResult> selector) { if (source == null) { throw Error.ArgumentNull("source"); } if (selector == null) { throw Error.ArgumentNull("selector"); } return SelectIterator(source, selector); } private static IEnumerable<TResult> SelectIterator<TSource, TResult>(IEnumerable<TSource> source, Func<TSource, int, TResult> selector) { int index = -1; foreach (TSource item in source) { index = checked(index + 1); yield return selector(item, index); } }
三:其他案例
其实有太多例子需要使用迭代器中的index值了,比如最近业务中要计算各个月份的环比率,用今天讲到的这个方法就可以非常完美的解决,简化后的代码如下。
public static void Main(string[] args) { var list = new List<int>() { 10, 20, 30,40,50, 60,70,80,90,100,110,120, }; var rateList = list.Select((item, index) => { return index == 0 ? 0 : Math.Round(((decimal)list[index] - list[index - 1]) / list[index - 1], 2); }).ToList(); rateList.ForEach(Console.WriteLine); } ------------------- output ------------------- 0 1 0.5 0.33 0.25 0.2 0.17 0.14 0.12 0.11 0.1 0.09 Press any key to continue . . .
好了,本篇来自于触景生情,希望您编码有帮助。
如您有更多问题与我互动,扫描下方进来吧~
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网
猜你喜欢:- 迭代器萃取与反向迭代器
- 浅谈python可迭代对象,迭代器
- 可迭代对象,迭代器(对象),生成器(对象)
- 终于把动态规划与策略迭代、值迭代讲清楚了
- 终于把动态规划与策略迭代、值迭代讲清楚了
- 搞清楚 Python 的迭代器、可迭代对象、生成器
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。