雁过请留痕...
代码改变世界

Linq学习之旅——Linq to Objects之延期执行方法(上篇)

2012-07-29 17:54  xiashengwang  阅读(2937)  评论(1编辑  收藏  举报

目录

1,Take 方法

2,TakeWhile 方法

3,Skip 方法

4,SkipWhile 方法

5,Reverse 方法

6,Distinct 方法

7,Union 方法

8,Concat 方法

    LINQ to Objects是 LINQ的基础,而 LINQ to SQL、 LINQ to XML是中间 LINQ提供程序,他们主要是把数据源转换成 LINQ to Objects兼容的类型,以便 LINQ to Objects进行操作。 LINQ to Objects就是直接对IEnumerable或泛型IEnumerable<T>集合进行查询。LINQ表达式是LINQ标准查询运算符的一部分,而LINQ标准查询运算符则是LINQ to Objects的基础。它们是一组静态方法,被定义在System.Linq.Enumerable和System.Linq.Queryable类中。这两个类中方法基本一致,唯一的不同点是System.Linq.Queryable类中方法会把LINQ表达式拆解成表达式目录树,其他一些Linq提供程序可以将这个表达式目录树翻译成查询语句,比如SQL语句,然后再执行相关操作。

    本文主要学习System.Linq.Enumerable的扩展方法,这些方法按照执行的行为不同,可以分为延期执行和立即执行。延期执行的运算符在枚举时被执行,下面要学习的就是延期执行方法的一部分。

1,Take 方法

    Take方法用于从一个序列的开头返回指定数量的元素。 

            string[] names = { "郭靖", "李莫愁", "欧阳晓晓", "黄蓉", "黄药师" };

            //直接输出前3个元素
            Console.WriteLine("Take方法直接输出前3个元素");
            foreach (var name in names.Take(3))
            {
                Console.WriteLine(name);
            }
            var query = from n in names
                        where n.Length == 2
                        select n;
            Console.WriteLine("\nTake方法输出查询结果的前1个元素");
            foreach (var s in query.Take(1))
            {
                Console.WriteLine(s);
            }

输出结果:

Take方法直接输出前3个元素
郭靖
李莫愁
欧阳晓晓

Take方法输出查询结果的前1个元素
郭靖

2,TakeWhile 方法

    TakeWhile方法获取序列中从开头起符合条件的元素,直到遇到不符合条件的元素为止的所有元素。条件代理部分有两种形式:

Func<TSource, bool> predicate

Func<TSource, int, bool> predicate 第二个参数是元素的索引

注意:当条件为假时,就停止了,后面的元素不会输出。

            string[] names = { "郭靖", "李莫愁", "欧阳晓晓", "黄蓉", "黄药师" };

            //输出名字小于4个字的元素
            var takeNames = names.TakeWhile(n => n.Length < 4);
            foreach (var name in takeNames)
            {
                Console.WriteLine(name);
            }
            Console.WriteLine("\nTakeWhile 带索引参数");
            //输出名字字数小于等于4 并且索引小于4的元素
            foreach (var name in names.TakeWhile((n, i) => n.Length <= 4 && i < 4))
            {
                Console.WriteLine(name);
            }

输出结果:

郭靖
李莫愁

TakeWhile 带索引参数
郭靖
李莫愁
欧阳晓晓
黄蓉

3,Skip 方法

    Skip方法用于跳过序列中指定个数的元素。

            string[] names = { "郭靖", "李莫愁", "欧阳晓晓", "黄蓉", "黄药师" };

            //跳过前3个元素
            Console.WriteLine("Take方法跳过前3个元素");
            foreach (var name in names.Skip(3))
            {
                Console.WriteLine(name);
            }
            var query = from n in names
                        where n.Length == 2
                        select n;
            Console.WriteLine("\nTake方法跳过查询结果的前1个元素");
            foreach (var s in query.Skip(1))
            {
                Console.WriteLine(s);
            }

输出结果:

Take方法跳过前3个元素
黄蓉
黄药师

Take方法跳过查询结果的前1个元素
黄蓉

4,SkipWhile 方法

    SkipWhile 方法用于只要满足指定的条件,就跳过序列中得元素。

注意当遇到条件为假时,就停止跳越了输出剩余的所有元素

            string[] names = { "郭靖", "李莫愁", "欧阳晓晓", "黄蓉", "黄药师" };

            Console.WriteLine("SkipWhile跳过名字为2个字的元素");
            foreach (var name in names.SkipWhile(n => n.Length == 2))
            {
                Console.WriteLine(name);
            }

            Console.WriteLine("\nSkipWhile跳过名字小于4个字,并且索引小于2");
            foreach (var s in names.SkipWhile((n, i) => n.Length < 4 && i < 2))
            {
                Console.WriteLine(s);
            }

输出结果:

SkipWhile跳过名字为2个字的元素
李莫愁
欧阳晓晓
黄蓉
黄药师

SkipWhile跳过名字小于4个字,并且索引小于2
欧阳晓晓
黄蓉
黄药师

5,Reverse 方法

    Reverse 方法用于反转序列中的元素。

            string[] names = { "郭靖", "李莫愁", "欧阳晓晓", "黄蓉", "黄药师" };

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

输出结果:

黄药师
黄蓉
欧阳晓晓
李莫愁
郭靖

6,Distinct 方法   

    Distinct 方法用于去除重复元素。

            string[] names = { "郭靖", "郭靖", "李莫愁", "欧阳晓晓", "欧阳晓晓", "黄蓉", "黄药师" };

            Console.WriteLine("含有重复元素的数组");
            foreach (var name in names)
            {
                Console.Write(name + " ");
            }
            Console.WriteLine("\n\n去除重复元素的数组");
            foreach (var name in names.Distinct())
            {
                Console.Write(name + " ");
            }

输出结果:

含有重复元素的数组
郭靖 郭靖 李莫愁 欧阳晓晓 欧阳晓晓 黄蓉 黄药师 

去除重复元素的数组
郭靖 李莫愁 欧阳晓晓 黄蓉 黄药师

自定义IEqualityComparer<T>接口的相等比较器

        public class MyEqualityComparer<T> : IEqualityComparer<T>
        {
            #region IEqualityComparer<T> 成员

            public bool Equals(T x, T y)
            {
                string temp = x as string;
                if (temp != null)
                {
                    if (temp == "欧阳晓晓") //对"欧阳晓晓"不过滤
                        return false;
                }
                if (x.GetHashCode() == y.GetHashCode())
                    return true;
                else
                    return false;
            }

            public int GetHashCode(T obj)
            {
                return obj.GetHashCode();
            }

            #endregion
        }
        private void DistinctDemo()
        {
            string[] names = { "郭靖", "郭靖", "李莫愁", "欧阳晓晓", "欧阳晓晓", "黄蓉", "黄药师" };

            Console.WriteLine("含有重复元素的数组");
            foreach (var name in names)
            {
                Console.Write(name + " ");
            }
            Console.WriteLine("\n\n去除重复元素的数组,实现自定义IEqualityComparer<T>");
            foreach (var name in names.Distinct(new MyEqualityComparer<string>()))
            {
                Console.Write(name + " ");
            }
        }

输出结果:

含有重复元素的数组
郭靖 郭靖 李莫愁 欧阳晓晓 欧阳晓晓 黄蓉 黄药师 

去除重复元素的数组,实现自定义IEqualityComparer<T>
郭靖 李莫愁 欧阳晓晓 欧阳晓晓 黄蓉 黄药师

7,Union 方法

    Union 方法 用于合并两个序列,并去掉重复元素。

            string[] names = { "郭靖", "郭靖", "李莫愁", "欧阳晓晓", "欧阳晓晓", "黄蓉", "黄药师" };

            Console.WriteLine("含有重复元素的数组");

            foreach (var name in names)
            {
                Console.Write(name + " ");
            }
            Console.WriteLine("\n\n去除重复元素的数组,实现自定义IEqualityComparer<T>");
            foreach (var name in names.Distinct(new MyEqualityComparer<string>()))
            {
                Console.Write(name + " ");
            }

输出结果:

合并后的元素
郭靖 李莫愁 欧阳晓晓 黄蓉 黄药师 杨过 

自定义IEqualityComparer<T>接口的相等比较器

            string[] names = { "郭靖", "李莫愁", "欧阳晓晓", "黄蓉", "黄药师" };
            string[] names2 = { "郭靖", "杨过", "欧阳晓晓" };

            Console.WriteLine("合并后的元素");
            foreach (var name in names.Union(names2,new MyEqualityComparer<string>()))
            {
                Console.Write(name + " ");
            }

输出结果:

合并后的元素
郭靖 李莫愁 欧阳晓晓 黄蓉 黄药师 杨过 欧阳晓晓

8,Concat 方法

    Concat 方法 用于连接两个序列,与Union不同,它不会过滤重复的元素。

            string[] names = { "郭靖", "李莫愁", "欧阳晓晓", "黄蓉", "黄药师" };
            string[] names2 = { "郭靖", "杨过", "欧阳晓晓" };

            Console.WriteLine("合并后的元素");
            foreach (var name in names.Concat(names2))
            {
                Console.Write(name + " ");
            }

输出元素:

合并后的元素
郭靖 李莫愁 欧阳晓晓 黄蓉 黄药师 郭靖 杨过 欧阳晓晓