Linq中SelectMany图文详解-Chinar

Chinar blog www.chinar.xin

SelectMany中文教程


本文提供全流程,中文翻译

助力快速理解 SelectMany 的高级用法

为初学者节省宝贵的时间,避免采坑!

Chinar —— 心分享、心创新!

我们的初衷是将一种简单的生活方式带给世人

使有限时间 具备无限可能

Chinar 教程效果:



全文高清图片,点击即可放大观看 (很多人竟然不知道)


1 Intro —— 简介


SelectMany对于初学者来讲,是一个比较难理解的函数。其内部逻辑,有点绕。

在使用上,对初学者来讲,尤其是容易懵逼…

但它的用途极其广泛,且极大的节省代码、提高代码可读性。

避免大量的循环代码

这里我以 4个例子,说明SelectMany的多种用法。

请大家仔细、耐心的看完。

1.1 Constructor ―― 构造函数

Wait —— 敬请期待
设置tag —— 格子=Grid;物品=Good;


举个例子

  /// <summary>
    /// 第一层:老爹
    /// </summary>
    public class One
    {
        public string    Name;    //名字
        public int       Age;     //年龄
        public List<Two> TwoList; //儿子


        public One(string name, int age, List<Two> twoList)
        {
            Name    = name;
            Age     = age;
            TwoList = twoList;
        }
    }


    /// <summary>
    /// 第二层:儿子
    /// </summary>
    public class Two
    {
        public string      Name;      //名字
        public int         Age;       //年龄
        public List<Three> ThreeList; //儿子


        public Two(string name, int age, List<Three> threeList)
        {
            Name      = name;
            Age       = age;
            ThreeList = threeList;
        }


        public override string ToString()
        {
            return $"{nameof(Name)}: {Name}, {nameof(Age)}: {Age}, {nameof(ThreeList)}: {ThreeList}";
        }
    }


    /// <summary>
    /// 第三层:孙子
    /// </summary>
    public class Three
    {
        public int Age;   //年龄
        public int Score; //分数


        public Three(int age, int score)
        {
            Age   = age;
            Score = score;
        }


        public override string ToString()
        {
            return $"{nameof(Age)}: {Age}, {nameof(Score)}: {Score}";
        }
    }

初始化,填入数据

为了便于大家理解,我用了
one、two、three 做为3层嵌套的子父类;
one 对应的数据值为: A、B、C、D

List<One> ones = new List<One> //第一层列表
{
    new One("A1", 40, new List<Two> //第二层
    {
        new Two("A2_0", 20,   new List<Three> {new Three(10, 100)}), //第三层
        new Two("A2_1", 200,  new List<Three> {new Three(10, 100)}), //第三层
        new Two("A2_2", 2000, new List<Three> {new Three(10, 100)})  //第三层
    }),
    new One("B1", 50, new List<Two>
    {
        new Two("B2", 30, new List<Three> {new Three(14, 70)})
    }),
    new One("C1", 70, new List<Two>
    {
        new Two("C2_0", 50, new List<Three> {new Three(25, 80)}),
        new Two("C2_1", 50, new List<Three> {new Three(25, 80)})
    }),
    new One("D1", 80, new List<Two>
    {
        new Two("D2", 60, new List<Three> {new Three(40, 50)})
    }),
};

2 Overload 1 —— 重载 1


我们来看下官方的代码注释:
//
// 摘要:
//     一个序列的每个元素投影 System.Collections.Generic.IEnumerable`1, ,并将合并为一个序列将结果序列。 每个源元素的索引用于该元素的投影表。
//
// 参数:
//   source:
//     一个要投影的值序列。
//
//   selector:
//     一个应用于每个源元素的转换函数;函数的第二个参数表示源元素的索引。
//
// 类型参数:
//   TSource:
//     中的元素的类型 source。
//
//   TResult:
//     返回的序列的元素的类型 selector。
//
// 返回结果:
//     System.Collections.Generic.IEnumerable`1 其元素是一种一对多转换函数对输入序列中的每个元素调用的结果。
//
// 异常:
//   T:System.ArgumentNullException:
//     source 或 selector 为 null。
public static IEnumerable<TResult> SelectMany<TSource, TResult>(this IEnumerable<TSource> source, Func<TSource, int, IEnumerable<TResult>> selector);

懵逼不?这才是重载第一个
不要怕,有我,跟我来看个栗子

 IEnumerable<List<Two>> onesSelect     = ones.Select(_ => _.TwoList);     //Select 返回 List<Two>
 IEnumerable<Two>       onesSelectMany = ones.SelectMany(_ => _.TwoList); //第一个重载:返回 Two
 foreach (var v in onesSelect)
 {
     Console.WriteLine(v); //v=List<Two>
 }

 Console.WriteLine("----------------------------");
 foreach (var v in onesSelectMany)
 {
     Console.WriteLine(v); //v=Two
 }

输出结果在这里插入图片描述
可以看出明显区别。

SelectMany 作用:

Ones列表中的 每个元素 One 的实例,
每个 One 实例下都对应了几个 TwoList 列表
将每个 TwoList 列表中的的元素 Two ,重新组合成一个包含了所有 TwoList的大列表;

还不理解?没事,我给你们准备了张图。

举个例子

在这里插入图片描述


支持

May Be —— 开发者,总有一天要做的事!


拥有自己的服务器,无需再找攻略

Chinar 提供一站式《零》基础教程

使有限时间 具备无限可能!

先点击领取 —— 阿里全产品优惠券 (享受最低优惠)


Chinar 免费服务器、建站教程全攻略!( Chinar Blog )


Chinar

END

本博客为非营利性个人原创,除部分有明确署名的作品外,所刊登的所有作品的著作权均为本人所拥有,本人保留所有法定权利。违者必究

对于需要复制、转载、链接和传播博客文章或内容的,请及时和本博主进行联系,留言,Email: [email protected]

对于经本博主明确授权和许可使用文章及内容的,使用时请注明文章或内容出处并注明网址

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章