Linq中带有迭代索引的Select扩展方法,为啥知道的人不多呢?

栏目: IT技术 · 发布时间: 4年前

内容简介:昨天在看C#函数式编程这本书的时候,有一处让我干着急,需求是这样: 给多行文字加上数字列表项。针对这个需求你会如何快捷高效的给每个项目加上数字编号呢? 我看书中是这样实现的,如下代码

一:背景

昨天在看C#函数式编程这本书的时候,有一处让我干着急,需求是这样: 给多行文字加上数字列表项。

Linq中带有迭代索引的Select扩展方法,为啥知道的人不多呢?

针对这个需求你会如何快捷高效的给每个项目加上数字编号呢? 我看书中是这样实现的,如下代码

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 . . .

好了,本篇来自于触景生情,希望您编码有帮助。

如您有更多问题与我互动,扫描下方进来吧~

Linq中带有迭代索引的Select扩展方法,为啥知道的人不多呢? Linq中带有迭代索引的Select扩展方法,为啥知道的人不多呢?


以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

艾伦•图灵传

艾伦•图灵传

(英)安德鲁·霍奇斯 / 孙天齐 / 湖南科学技术出版社 / 2012-8-1 / 68.00元

《艾伦·图灵传:如谜的解谜者》是图灵诞辰100周年纪念版,印制工艺更为精美。本书是世界共认的最权威的图灵传记。艾伦?图灵是现代人工智能的鼻祖,在24岁时奠定了计算机的理论基础。二战期间,他为盟军破译密码,为结束战争做出巨大贡献。战后,他开创性地提出人工智能的概念,并做了大量的前期工作。因同性恋问题事发,被迫注射激素,后来吃毒苹果而死。作者是一名数学家,也是一名同性恋者。他对图灵的生平有切身的体会,......一起来看看 《艾伦•图灵传》 这本书的介绍吧!

JSON 在线解析
JSON 在线解析

在线 JSON 格式化工具

MD5 加密
MD5 加密

MD5 加密工具

SHA 加密
SHA 加密

SHA 加密工具