新普京网站-澳门新普京 > 前端 > 创制对象列表的两样方法【新普京网站】

创制对象列表的两样方法【新普京网站】

2019/12/30 02:34

本文由码农网 – 小峰原创翻译,转发请看清文末的转发必要,应接加入大家的付费投稿安顿!

LINQ基础(二),linq基础

  本文首要介绍LINQ查询操作符

  LINQ查询为最常用的操作符定义了一个声称语法。还应该有好多询问操作符可用于Enumerable类。

  上边包车型的士例子供给用到LINQ底工(风姿罗曼蒂克State of Qatar(

1.筛选

  LINQ查询利用where子句增多条件表达式来筛选,where子句能够统生龙活虎八个表明式。

var racers = from r in Formula1.GetChampions() 
                    where r.Wins>15 && 
                        (r.Country == "Brazil" || r.Country =="Austria")
                    select r;

        foreach(var r in racers)
        {
            Console.WriteLine("{0:A}", r);
        }

  上述LINQ表达式映射为C# LINQ查询的强大方法:
  var racers = Formula1.GetChampions().Where(r =>where r.Wins>15 &&
    (r.Country == "Brazil" || r.Country =="Austria")).Select(r => r);

  注意,实际不是为此查询都能够动用LINQ查询语法,亦不是颇有的恢宏方法都映射到LINQ查询。高端查询需求选用扩大方法。

2.用索引筛选

  不能够选用LINQ查询的四个事例是Where(卡塔尔(قطر‎方法的重载。在WHere(卡塔尔国方法的重载中,能够传递第叁个参数————索引。索引是筛选器重回的每一个结果的流量计。能够在表明式中利用这几个目录,试行基于索引的乘除:

var racers = Formula1.GetChampions().
            Where((r, index) => r.LastName.StartsWith("A") && index % 2 != 0);
        foreach (var r in racers)
        {
            Console.WriteLine("{0:A}", r);
        }

 

3.类型筛选
  为了实行基于项目的筛选,能够应用OfType(卡塔尔扩充方法。

object[] data = { "one", 2, 3, "four", "five", 6 };
          var query = data.OfType<string>();
          foreach (var s in query)
          {
            Console.WriteLine(s);
          }

  输出:
    one
    four
    five
  从集结仅重回字符串。

4.复合的from子句新普京网站

  若是急需凭借指标的积极分子举办筛选,而该成员本身是一个类别,就足以应用复合from子句。比如,LINQ根基(生龙活虎卡塔尔(قطر‎(

  筛选驾车法拉利的之所以季军:  

  var ferrariDrivers = from r in Formula1.GetChampions()
                           from c in r.Cars
                           where c == "Ferrari"
                           orderby r.LastName
                           select r.FirstName + " " + r.LastName;

      foreach (var racer in ferrariDrivers)
      {
        Console.WriteLine(racer);
      }

澳门新普京 , 

  第三个from子句访谈Formula1.GetChampions(卡塔尔方法重临的Racer对象,第1个from子句访谈Racer类的Cars属性,以回到所以sting类型的赛车。

  C#编译器把复合的from子句和LINQ查询转变为SelectMany(卡塔尔扩大方法。SelectMany(卡塔尔扩充方法能够迭代类别中的系列。
  SelectMany(卡塔尔国的重载版本:
  public static IEnumerable<TResult> SelectMany<TSource, TCollection, TResult>(this IEnumerable<TSource> source,
    Func<TSource, IEnumerable<TCollection>> collectionSelector,
      Func<TSource, TCollection, TResult> resultSelector);

  第二个参数是隐式参数,它从Formula1.GetChampions(卡塔尔国方法选拔Racer对象系列。第贰个参数是collectionSelector委托,在那之中定义了中间系列,是连串的队列,本例子为Cars。第多个参数也是贰个寄托,为各样Racer对象的Cars属性的种种成分调用那个委托。

  这里Cars是多个字符串数组,会将每一种Racer和每一种字符串作为参数,调用这几个委托。  

var ferrariDrivers = Formula1.GetChampions().SelectMany(
            c => c.Cars, (r, s) => new { Racer=r,Car =s}).Where(
            s =>s.Car == "Ferrari").OrderBy(
            r => r.Racer.LastName).Select(r => r.Racer.FirstName + " " + r.Racer.LastName);

        foreach (var racer in ferrariDrivers)
        {
            Console.WriteLine(racer);
        }

5.排序
  要对队列排序,可以行使后面使用过的orderby.也得以动用orderrby descending子句(降序)。 

var racers = (from r in Formula1.GetChampions()
                      orderby r.Country  descending
                      select r);

        foreach (var racer in racers)
        {
            Console.WriteLine("{0}: {1}, {2}", racer.Country, racer.LastName, racer.FirstName);
        }

  orderby子句分析为OrderBy(卡塔尔国方法,orderby r.Country descending深入深入分析为OrderByDescending(State of Qatar方法:
  var racers = Formula1.GetChampions().OrderByDescending(r => r.Country).Select(r=>r);

  OrderBy(卡塔尔和OrderByDescending(State of Qatar方法重返IOrderEnumerable<TSource>。那个接口派生自IEnumerable<TSource>接口,但含有一个极其的措施CreateOrderEnumerable<TSource>(卡塔尔(قطر‎方法。那几个法子用于进一层给连串排序,可以在最后一个参数钦命升序依旧降序:   

// 摘要:
        //     根据某个键对 System.Linq.IOrderedEnumerable<TElement> 的元素执行后续排序。
        //
        // 参数:
        //   keySelector:
        //     用于提取每个元素的键的 System.Func<T,TResult>。
        //
        //   comparer:
        //     用于比较键在返回序列中的位置的 System.Collections.Generic.IComparer<T>。
        //
        //   descending:
        //     如果为 true,则对元素进行降序排序;如果为 false,则对元素进行升序排序。
        //
        // 类型参数:
        //   TKey:
        //     keySelector 生成的键的类型。
        //
        // 返回结果:
        //     一个 System.Linq.IOrderedEnumerable<TElement>,其元素按键排序。
        IOrderedEnumerable<TElement> CreateOrderedEnumerable<TKey>(Func<TElement, TKey> keySelector, IComparer<TKey> comparer, bool descending);

  例子:

// Create an array of strings to sort.
              string[] fruits = { "apricot", "orange", "banana", "mango", "apple", "grape", "strawberry" };
              // First sort the strings by their length.
              IOrderedEnumerable<string> sortedFruits2 =
                  fruits.OrderBy(fruit => fruit.Length);
              // Secondarily sort the strings alphabetically, using the default comparer.
              IOrderedEnumerable<string> sortedFruits3 =
                  sortedFruits2.CreateOrderedEnumerable<string>(
                      fruit => fruit,
                      Comparer<string>.Default, false);

  使用ThenBy和ThenByDescending(State of Qatar方法开展更为排序,能够拉长放肆多少个:
  var racers = Formula1.GetChampions().OrderByDescending(r => r.Country).ThenByDescending(
    r => r.LastName).ThenByDescending(r => r.FirstName).Select(r => r);

6.分组
  要依照叁个十分重要字值对查询结果分组,能够运用group子句。

// group r by r.Country into g 根据Country属性组合所有的赛车手,并定义为一个新的集合g,用于访问分组的结果信息。
        //select子句创建一个带Country和Count属性的匿名类型。Country = g.Key Key是r.Country
        var countries = from r in Formula1.GetChampions()
                      group r by r.Country into g
                      orderby g.Count() descending, g.Key
                      where g.Count() >= 2
                      select new
                      {
                        Country = g.Key,
                        Count = g.Count()
                      };
        foreach (var item in countries)
          {
            Console.WriteLine("{0, -10} {1}", item.Country, item.Count);
          }

  输出:
  澳门新普京 1

  使用扩充方法试行同生龙活虎的操作,把group r by r.Country 子句分析为GroupBy(卡塔尔国方法。在GroupBy(卡塔尔方法的宣示中,它回到达成了IGrouping<TKey, TSource>接口的枚举对象。IGrouping<TKey, TSource>接口定义了Key属性,所以在调用了这几个措施后,能够访谈分组的根本字:
  public static IEnumerable<IGrouping<TKey, TSource>> GroupBy<TSource, TKey>(this IEnumerable<TSource> source,
    Func<TSource, TKey> keySelector);
  使用GroupBy方法:

 var countries = Formula1.GetChampions().GroupBy(r => r.Country).OrderByDescending(
            g => g.Count()).ThenBy(g => g.Key).Where(g => g.Count() >= 2).Select(
            g=>new
                      {
                          Country = g.Key,
                          Count = g.Count()
                      });

7.对嵌套的对象分组

  假如获得的分组的指标急需包蕴嵌套的队列,就足以校正select子句创建无名类型。   

//返回的对象不仅需要包含国家名和赛车手这两个属性,还应包含赛车手集合。
        //使用from r1 in g orderby r1.LastName select r1.FirstName + " " + r1.LastName 内部子句
        var countries = from r in Formula1.GetChampions()
                      group r by r.Country into g
                      orderby g.Count() descending, g.Key
                      where g.Count() >= 2
                      select new
                      {
                        Country = g.Key,
                        Count = g.Count(),
                        Racers = from r1 in g
                                 orderby r1.LastName
                                 select r1.FirstName + " " + r1.LastName
                      };
      foreach (var item in countries)
      {
        Console.WriteLine("{0, -10} {1}", item.Country, item.Count);
        foreach (var name in item.Racers)
        {
          Console.Write("{0}; ", name);
        }
        Console.WriteLine();
      }

8.内连接

  使用join子句可以依赖特定的尺码合併七个数据源,但早先要博得多少个一连的列表。

  使用了LINQ基础(一)(  

//GetChampions获得冠军赛车手
        var racers = from r in Formula1.GetChampions()
                   from y in r.Years
                   select new
                   {
                     Year = y,
                     Name = r.FirstName + " " + r.LastName
                   };
        //GetContructorChampions获取冠军车队
          var teams = from t in Formula1.GetContructorChampions()
                      from y in t.Years
                      select new
                      {
                        Year = y,
                        Name = t.Name
                      };
        //得到每一年获得冠军的赛车手和车队
        //通过join t in teams on r.Year equals t.Year into rt 子句连接两个数据源
          var racersAndTeams =
            (from r in racers
             join t in teams on r.Year equals t.Year into rt
             from t in rt.DefaultIfEmpty()
             orderby r.Year
             select new
             {
               Year = r.Year,
               Champion = r.Name,
               Constructor = t == null ? "no constructor championship" : t.Name
             });

          Console.WriteLine("Year  Championtt   Constructor Title");
          foreach (var item in racersAndTeams)
          {
            Console.WriteLine("{0}: {1,-20} {2}",
               item.Year, item.Champion, item.Constructor);
          }

 

 

9.左连接
  使用内连接再次来到相配r.Year equals t.Year的结果。左连接再次回到左侧数据源的全体因素,纵然在侧面的数量源中未有相配的要素。   

var racers = from r in Formula1.GetChampions()
                   from y in r.Years
                   select new
                   {
                     Year = y,
                     Name = r.FirstName + " " + r.LastName
                   };

      var teams = from t in Formula1.GetContructorChampions()
                  from y in t.Years
                  select new
                  {
                    Year = y,
                    Name = t.Name
                  };
        //左连接用join和DefaultIfEmpty方法定义。
        //如果查询到左侧数据源没有和右边数据源Year相同的结果,使用DefaultIfEmpty方法定义右侧的默认值(为空)
      var racersAndTeams =
        (from r in racers
         join t in teams on r.Year equals t.Year into rt
         from t in rt.DefaultIfEmpty()
         orderby r.Year
         select new
         {
           Year = r.Year,
           Champion = r.Name,
           Constructor = t == null ? "no constructor championship" : t.Name
         });

      Console.WriteLine("Year  Championtt   Constructor Title");
      foreach (var item in racersAndTeams)
      {
        Console.WriteLine("{0}: {1,-20} {2}",
           item.Year, item.Champion, item.Constructor);
      }

10.组连接
  组连接相同内屡次三番,内延续通过某蓬蓬勃勃项连接八个数据源(如 r.Year equals t.Year),组连接使用生龙活虎组项连接,比如下边包车型大巴例子,
  通过 new
    {
      FirstName = r.FirstName,
      LastName = r.LastName
    }
    equals
    new
    {
      FirstName = r2.FirstName,
      LastName = r2.LastName
    }
  连接三个数据源   

var racers = Formula1.GetChampionships()
        .SelectMany(cs => new List<RacerInfo>()
        {
         new RacerInfo {
           Year = cs.Year,
           Position = 1,
           FirstName = cs.First.FirstName(),
           LastName = cs.First.LastName()        
         },
         new RacerInfo {
           Year = cs.Year,
           Position = 2,
           FirstName = cs.Second.FirstName(),
           LastName = cs.Second.LastName()        
         },
         new RacerInfo {
           Year = cs.Year,
           Position = 3,
           FirstName = cs.Third.FirstName(),
           LastName = cs.Third.LastName()        
         }
       });

      var q = (from r in Formula1.GetChampions()
               join r2 in racers on
               new
               {
                 FirstName = r.FirstName,
                 LastName = r.LastName
               }
               equals
               new
               {
                 FirstName = r2.FirstName,
                 LastName = r2.LastName
               }
               into yearResults
               select new
               {
                 FirstName = r.FirstName,
                 LastName = r.LastName,
                 Wins = r.Wins,
                 Starts = r.Starts,
                 Results = yearResults
               });

      foreach (var r in q)
      {
        Console.WriteLine("{0} {1}", r.FirstName, r.LastName);
        foreach (var results in r.Results)
        {
          Console.WriteLine("{0} {1}", results.Year, results.Position);
        }
      }

 

11.凑合操作

  扩充方法Distinct(卡塔尔(قطر‎,Union(State of Qatar,Intersect(卡塔尔(قطر‎(获取交集),Except(卡塔尔国都是会晤操作。  

//获取同时驾驶Ferrari和驾驶McLaren获得过冠军的赛车手
        static void SetOperations()
        {
            //定义一个委托,用来查询驾驶Ferrari获得过冠军的赛车手和驾驶McLaren获得过冠军的赛车手
          Func<string, IEnumerable<Racer>> racersByCar =
              car => from r in Formula1.GetChampions()
                     from c in r.Cars
                     where c == car
                     orderby r.LastName
                     select r;

          Console.WriteLine("World champion with Ferrari and McLaren");
          //使用Intersect方法获取两个数据源的交集
          foreach (var racer in racersByCar("Ferrari").Intersect(racersByCar("McLaren")))
          {
            Console.WriteLine(racer);
          }
        }

 

12.合并
  Zip(卡塔尔(قطر‎方法是.NET 4.0新扩张的,允许用一个为此函数把多少个相关的行列归拢为叁个。

  对于联合,第多少个汇集中的第意气风发项与第二个聚众的首先项联合,第三个聚众中的第二项与第4个汇集的第二项联合,由此及彼。假诺多个类别的项数分歧,Zip(卡塔尔国方法就能够在到达很小集结的末段时停下。

  第一个聚众中的成分有一个Name属性,第三个集聚中的成分有LastName和Starts属性。

  在racerNames集合上选拔Zip(卡塔尔方法,须要把第一个会集racerNamesAndStarts作为第多个参数。第四个参数是一个信托,它经过参数first选取第三个集聚的成分,通过参数second接收第三个聚众的因素。其实现代码重回叁个字符串:  

var racerNames = from r in Formula1.GetChampions()
                       where r.Country == "Italy"
                       orderby r.Wins descending
                       select new
                       {
                         Name = r.FirstName + " " + r.LastName
                       };

          var racerNamesAndStarts = from r in Formula1.GetChampions()
                                    where r.Country == "Italy"
                                    orderby r.Wins descending
                                    select new
                                    {
                                      LastName = r.LastName,
                                      Starts = r.Starts
                                    };


          var racers = racerNames.Zip(racerNamesAndStarts, (first, second) => first.Name + ", starts: " + second.Starts);
          foreach (var r in racers)
          {
              Console.WriteLine(r);
          }

13.分区
  扩大方法Take(卡塔尔和Skip(卡塔尔(قطر‎等的分区操作可用于分页。
  比方,在首先页只突显5个赛车手,下少年老成页彰显接下去的5个赛车手...
  Skip(page * pageSizeState of Qatar方法调到钦命索引出,忽视前边的数额。Take(pageSize卡塔尔国方法显示pageSize条数据   

 int pageSize = 5;

          int numberPages = (int)Math.Ceiling(Formula1.GetChampions().Count() /
                (double)pageSize);

          for (int page = 0; page < numberPages; page++)
          {
            Console.WriteLine("Page {0}", page);

            var racers =
               (from r in Formula1.GetChampions()
                orderby r.LastName, r.FirstName
                select r.FirstName + " " + r.LastName).
               Skip(page * pageSize).Take(pageSize);

            foreach (var name in racers)
            {
              Console.WriteLine(name);
            }
            Console.WriteLine();
          }

  TakeWhile(State of Qatar和SkipWhile(卡塔尔(قطر‎方法,传递二个信托,满意那么些规格的数码就领取或跳转:
  public static IEnumerable<TSource> SkipWhile<TSource>(this IEnumerable<TSource> source, Func<TSource, bool> predicate);

14.集合操作符

  聚合操作符(如Count(State of Qatar,Sum(卡塔尔(قطر‎,Min(卡塔尔国,Max(State of Qatar,Average(State of Qatar,Aggregate(卡塔尔)不回来叁个行列,而是回到二个值。

  比如,使用Count方法运用于Racer的Years属性,筛选获得亚军次数当先3次的跑车手。因为一再接纳r.Years.Count(State of Qatar,所以使用let子句定义了二个变量。  

  

var query = from r in Formula1.GetChampions()
                  let numberYears = r.Years.Count()
                  where numberYears >= 3
                  orderby numberYears descending, r.LastName
                  select new
                  {
                    Name = r.FirstName + " " + r.LastName,
                    TimesChampion = numberYears
                  };

          foreach (var r in query)
          {
            Console.WriteLine("{0} {1}", r.Name, r.TimesChampion);
          }

  Aggregate(State of Qatar方法传递二个委托,将数据源中的各样成分作为委托的参数,并动用钦定的函数累计。

15.改造操作符

  LINQ基础(一)(  

    

//转换为数组
        var names = new List<string> { "Nino", "Alberto", "Juan", "Mike", "Phil" };

        var namesWithJ = (from n in names
                         where n.StartsWith("J")
                         orderby n
                         select n).ToList();

  转换为Lookup<TKey,TElement>   

//把Car赛车属性作为键,每个键关联多个车手Racer
            var racers = (from r in Formula1.GetChampions()
                      from c in r.Cars
                      select new
                      {
                          Car = c,
                          Racer = r
                          }).ToLookup(cr => cr.Car, cr => cr.Racer);
            foreach (var v in racers)
            {
                Console.Write(v.Key+"........");
                foreach (var k in racers[v.Key])
                {
                    Console.WriteLine(k);
                }
            }

  ToLookup(cr => cr.Car, cr => cr.Racer卡塔尔(قطر‎方法的叁个重载版本传递三个键和三个成分选取器

  如果须要在非类型化的群集上行使LINQ查询,能够应用Cast(State of Qatar方法,定义强类型化的查询:  

var list = new System.Collections.ArrayList(Formula1.GetChampions() as System.Collections.ICollection);

          var query = from r in list.Cast<Racer>()
                      where r.Country == "USA"
                      orderby r.Wins descending
                      select r;
          foreach (var racer in query)
          {
            Console.WriteLine("{0:A}", racer);
          }

 

  Cast<Racer>(卡塔尔将 System.Collections.IEnumerable 的成分免强调换为钦赐的类型。

16.生成操作符

  生成操作符Range(卡塔尔(قطر‎,Empty(卡塔尔国,Repeat(卡塔尔国方法不是扩张方法,而是回到系列的健康静态方法。在LING to Object中,这个措施可用于Enumerable类。

  Range(State of Qatar方法用来填充贰个约束的数字。第一个参数作为初叶值,第三个参数作为要填写的项数:
    var values = Enumerable.Range(1,20);
  结果为1至20的集合。

  能够把该结果与其余扩张方法统风流倜傥:
    var values = Enumerable.Range(1,20).Select(n=> n*3);

  Empty(卡塔尔(قطر‎方法重临一个不重回值的迭代器,它用来须求叁个汇合的参数,此中可以给参数字传送递空会集。
  Repeat(卡塔尔方法重临钦赐个数的重复值的成团迭代器。

本文首要介绍LINQ查询操作符 LINQ查询为最常用的操作符定义了三个声称语法。还也会有好些个查询操作符可用于Enumerable类。...

玩转C#可有趣了。在此篇随笔中,大家将介绍怎么着用区别的方法成立对象列表。由此,场景是这么的,有叁个MVC应用程序,小编索要将5个空行(5个对象列表)绑定到grid表格,以便批量布置记录。所以无论曾几何时笔者展开这个页面,grid在可编写制定形式下表现5个空行。

在这里篇小说中,为了越来越好的申明,笔者动用了“Book”的例证。举个例子,纵然小编想添增加本书到叁个教室管理软件。首先,让我们成立三个主干的POCO类——Book——它有部分品质,看起来就像是那样:

public class Book
{
   public string BookName { get; set; } = string.Empty;
   public string Author { get; set; } = string.Empty;
   public string ISBN { get; set; } = string.Empty;
}

好的,让我们从基本语法到高端语法伊始搜求吧。在C#3.0以前,要增添对象并最初化集结,大家日常是这么做的:

var bookList = new List<Book>();
// Intiazize the object and add it to the collection
var book1 = new Book();
bookList.Add(book1);
var book2 = new Book();
bookList.Add(book2);

另后生可畏种方式是接受“for循环”,如下所示:

var bookList = new List<Book>();
// Another one is using for loop
for(int i = 0; i < 2; i++)
{
     bookList.Add(new Book());
}

另风流罗曼蒂克种方式是采纳AddRange(卡塔尔国方法,它将对象增加到钦赐的集纳中。

var bookList = new List<Book>();
// Using AddRange method.
bookList.AddRange(new[] {
                    new Book(),
                    new Book()
});

C#3.0推动了超级多狠抓功效。在那之中之生机勃勃正是Collection Initializers。那是二个用于创立集结的抽水语法。

// using collection initializer
var bookList = new List<Book>()
{
  new Book(),
  new Book(),
  new Book()
};
上一篇:没有了 下一篇:没有了