Select和SelectMany

一、带有函数调用功能的选择

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace 带有函数调用功能的选择
{
    class Program
    {
        static void Main(string[] args)
        {
            DateTime start = DateTime.Now;
            const long upper = 1000000;
            var numbers = new long[upper];
            for (long i = 2000; i <5000 ; i++)
            {
                numbers[i] = i + 1;
            }
            var primes = from n in numbers
                         where IsPrime(n)
                         select n;
            //BuildPrimes(upper);
            //var primes = from n in numbers
            //             where IsPrime2(n)
            //             select n;
            DateTime stop = DateTime.Now;
            StringBuilder builder = new StringBuilder();
            Array.ForEach(primes.ToArray(), n => builder.AppendFormat("{0}\n", n));
            Console.Write(builder.ToString());
            Console.WriteLine("Elapsed:{0}", Elasped(start, stop));
            Console.ReadKey();
        }
        /// <summary>
        /// 判断素数方法
        /// </summary>
        /// <param name="num">大于等于1小于den</param>
        /// <param name="den">目标数</param>
        /// <returns></returns>
        private static long Gcd(long num,long den)
        {
            return den % num == 1 ? 1 : den % num == 0 ? num : Gcd(den % num, num);
        }
        /// <summary>
        /// 用于观察某个函数执行的时间
        /// </summary>
        /// <param name="start"></param>
        /// <param name="stop"></param>
        /// <returns></returns>
        private static string Elasped(DateTime start,DateTime stop)
        {
            TimeSpan span = stop - start;
            return string.Format("Days:{0},Hours:{1},Minutes:{2},Seconds:{3},Miles:{4}",
                span.Days, span.Hours, span.Minutes, span.Seconds, span.Milliseconds);
        }
        /// <summary>
        /// 判断v是否为素数,以下两种不同办法
        /// </summary>
        /// <param name="v"></param>
        /// <returns></returns>
        private static bool IsPrime(long v)
        {
            if (v <= 1)
                return false;
            for (long i = 1; i < v; i++)
                if (Gcd(i, v) > 1)
                    return false;
            return true;
        }
        private static bool IsPrime2(long v)
        {
            for (int i = 0; i < Primes.Count; i++)
            {
                if (v % Primes[i] == 0)
                    return false;
                if (Primes[i] >= Math.Sqrt(v))
                    return true;
            }
            return true;
        }
        private static List<long> Primes = new List<long>();
        private static void BuildPrimes(long max)
        {
            Primes.Add(2);
            if (max < 3)
                return;
            for (long i = 0; i <= max; i++)
                if (IsPrime2(i))
                    Primes.Add(i);
        }
    }
}


二、使用Select谓词
     Select子句可以通过调用函数的方式进行计算,而这些谓词也可以直接使用。
【示例】
using System;
using System.Linq;

namespace 使用select谓词
{
    class Program
    {
        static void Main(string[] args)
        {
            var number =new int[]{ 2,3,4,5,6};
            var result = from n in number
                         select n * 2;   
            //foreach (var item in result)
            //{
            //    Console.Write(item + "  ");
            //}
            Array.ForEach(result.ToArray(), n => Console.Write(n + " "));//2,4,6,8,10
            Console.ReadKey();
        }
    }
}

三、从数据访问层返回自定义业务对象

     如何在称之为业务层的地方使用linq?我们需要在查询中构造已知类型而不是匿名类型,而且业务层中的这个函数需要返回IEnuerable<T>对象,其实T就是业务实体。

3.1 定义一个业务实体,并重写ToString()方法,用于转储实体状态

using System;
using System.Linq;
using System.Text;
using System.Reflection;

namespace 通过LINQ返回自定义业务对象
{
    /// <summary>
    /// 业务实体类
    /// </summary>
    public class Supplier
    {
        public int SupplierID { get; set; }
        public string CompanyName { get; set; }
        public string ContactName { get; set; }
        public string ContactTitle { get; set; }
        public string Address { get; set; }
        public string City { get; set; }
        public string Region { get; set; }
        public string PostalCode { get; set; }
        public string Country { get; set; }
        public string Phone { get; set; }
        public string Fax { get; set; }
        public string HomePage { get; set; }
        /// <summary>
        /// 转储实体状态
        /// </summary>
        /// <returns></returns>
        public override string ToString()
        {
            StringBuilder builder = new StringBuilder();
            PropertyInfo[] props = this.GetType().GetProperties();

            //use array for each
            Array.ForEach(props.ToArray(), p => builder.AppendFormat("{0}:{1}", p.Name,
                 p.GetValue(this, null) == null ? "<empty>\n" 
                 : p.GetValue(this,null).ToString() + "\n"));

            return builder.ToString();
        }
    }
}

3.2 定义IDataReader的扩展方法并有一个泛型委托Func用于提供全部的空值检查

using System;
using System.Data;

namespace 通过LINQ返回自定义业务对象
{
    public static class ExtendsReader
    {
        /// <summary>
        /// 泛型委托Func用于提供全部的空值检查
        /// </summary>
        static Func<string, IDataReader, string, string> SafeRead =
            (fieldName, reader, defaultValue) =>
            reader[fieldName] != null ? (string)Convert.ChangeType(reader[fieldName], 
                typeof(string)) : defaultValue;
        /// <summary>
        /// 调用泛型委托,实现对全部字段的空值检查,这是一个扩展方法
        /// </summary>
        /// <param name="reader"></param>
        /// <returns></returns>
        public static Supplier ReadSupplier(this IDataReader reader)
        {
            Supplier supplier = new Supplier();
            supplier.SupplierID = reader.GetInt32(0);
            supplier.CompanyName = SafeRead("CompanyName", reader, " ");
            supplier.ContactName = SafeRead("ContactName", reader, " ");
            supplier.ContactTitle = SafeRead("ContactTitle", reader, " ");
            supplier.Address = SafeRead("Address", reader, " ");
            supplier.City = SafeRead("City", reader, " ");
            supplier.Region = SafeRead("Region", reader, " ");
            supplier.PostalCode = SafeRead("PostalCode", reader, " ");
            supplier.Country = SafeRead("Country", reader, " ");
            supplier.Phone = SafeRead("Phone", reader, " ");
            supplier.Fax = SafeRead("fax", reader, " ");
            supplier.HomePage = SafeRead("HomePage", reader, " ");

            return supplier;
        }
    }
}

3.3 读取所有供应商的方法

using System;
using System.Collections.Generic;
using System.Linq;
using System.Data;
using System.Data.SqlClient;

namespace 通过LINQ返回自定义业务对象
{
    public static class DataAccess
    {
        private static readonly string connectionString = "Data Source=.; Initial Catalog=pubs; Integrated Security=SSPI;";
        /// <summary>
        /// 用于读取所有供应商的泛型方法
        /// </summary>
        /// <param name="predicate">筛选结果集</param>
        /// <returns></returns>
        public static IEnumerable<Supplier> 
            ReadSuppliers(Func<Supplier,bool> predicate)
        {
            IEnumerable<Supplier> suppliers = ReadSuppliers();
            return (from s in suppliers select s).Where(predicate);
        }
        public static IEnumerable<Supplier> ReadSuppliers()
        {
            using(SqlConnection con=new SqlConnection(connectionString))
            {
                con.Open();
                SqlCommand com = new SqlCommand("select * from suppliers", con);
                IDataReader reader = com.ExecuteReader();
                List<Supplier> list = new List<Supplier>();
                while (reader.Read())
                {
                    list.Add(reader.ReadSupplier());
                }
                return list;
            }
        }
    }
}

3.4 执行

using System;
using System.Collections.Generic;
using System.Linq;

namespace 通过LINQ返回自定义业务对象
{
    class Program
    {
        static void Main(string[] args)
        {
            IEnumerable<Supplier> USSuppliers = DataAccess.ReadSuppliers(s => s.Country == "USA");

            Array.ForEach(USSuppliers.ToArray(), s => Console.WriteLine(s));
            Console.ReadKey();
        }
    }
}

四、使用Select的索引打乱数组

using System;
using System.Linq;

namespace 使用Select的索引打乱数组
{
    class Program
    {
        static void Main(string[] args)
        {
            int[] cards = new int[20];
            Random random = new Random();
            var result = cards.Select((num, index) =>
              new { Key = index, Random = random.Next(200) });
            Array.ForEach(result.OrderBy(s => s.Random).ToArray(),
                s => Console.WriteLine(s));
            Console.ReadLine();
        }
    }
}


五、使用Select将单词的首字母改为大写
using System;
using System.Collections.Generic;
using System.Linq;

namespace LINQ
{
    class Program
    {
        static void Main(string[] args)
        {
            string str = "my  name is  xushuai";
            var strArray = str.Split(new char[] { ' '}, StringSplitOptions.RemoveEmptyEntries);
            var result = from s in strArray select s.Replace(s[0], Convert.ToChar(s[0].ToString().ToUpper()));
            result.WriteLineAll();
            Console.ReadLine();
        }
    }
    public static class Extender
    {
        public static void WriteLineAll<T>(this IEnumerable<T> ary)
        {
            Array.ForEach(ary.ToArray(), item => Console.WriteLine(item));
        }
    }
}

六、从多个源中投影出新类型
当LINQ查询使用一个或多个源类型中的元素来定义新类型时,就叫做一个投影。编译器会发出一个类,其类名中含有 AnonymousType字样。用于投影出新类型的方法共有两个:Select和SelectMany。当我们在查询中用到了多个from子句时,就会用到SelectMany方法。
【示例】
using System;
using System.Collections.Generic;
using System.Linq;

namespace 从多个源中投影出新类型
{
    class Program
    {
        static void Main(string[] args)
        {
            List<Customer> listC = new List<Customer>
            {
                new Customer {ID=1,CompanyName="xiaoxu" },
                new Customer {ID=2,CompanyName="daxiang"}
            };
            List<Order> listO = new List<Order>
            {
                new Order {ID=1,ItemScription="hahahahahahahah" },
                new Order {ID=2,ItemScription="chsihsidjsidjsidj" },
                new Order {ID=3,ItemScription="但是都是大祭司大祭司" }
            };
            var orderInfo = from c in listC
                            from o in listO
                            where c.ID == o.ID
                            //此时,投影出一个新类型(匿名类型),含有一个Name和Item属性
                            select new { Name = c.CompanyName, Item = o.ItemScription };
            Array.ForEach(orderInfo.ToArray(),
                i => Console.WriteLine("Company:{0},Item:{1}", i.Name, i.Item));
            Console.ReadKey();
        }
    }
    /// <summary>
    /// 实体类
    /// </summary>
    public class Customer
    {
        public int ID { get; set; }
        public string CompanyName { get; set; }
    }
    /// <summary>
    /// 实体类
    /// </summary>
    public class Order
    {
        public int ID { get; set; }
        public string ItemScription { get; set; }
    }
}


七、在SelectMany中使用索引

          SelectMany是一个扩展方法,其LINQ关键字是select,支持多个源序列。
【示例】

using System;
using System.Collections.Generic;
using System.Linq;

namespace 在SelectMany中使用索引
{
    class Program
    {
        static void Main(string[] args)
        {
            List<Customer> listC = new List<Customer>
            {
                new Customer {ID=1,CompanyName="xiaoxu" },
                new Customer {ID=2,CompanyName="daxiang"}
            };
            List<Order> listO = new List<Order>
            {
                new Order {ID=1, CustomerID=2,ItemScription="hahahahahahahah" },
                new Order {ID=2,CustomerID=3,ItemScription="chsihsidjsidjsidj" },
                new Order {ID=3,CustomerID=1,ItemScription="但是都是大祭司大祭司" }
            };
            var orderInfo = listC.SelectMany(
                (c, index) => from o in listO
                              where o.CustomerID == c.ID     
                              select new
                              {
                                  Key = index + 1,
                                  Customer = c.CompanyName,
                                  Item = o.ItemScription
                              });
            Array.ForEach(orderInfo.ToArray(), o => Console.WriteLine(
                 "Key:{0},Name:{1},Item:{2}", o.Key, o.Customer, o.Item));
            Console.ReadKey();
        }
    }
    /// <summary>
    /// 实体类
    /// </summary>
    public class Customer
    {
        public int ID { get; set; }
        public string CompanyName { get; set; }
    }
    /// <summary>
    /// 实体类
    /// </summary>
    public class Order
    {
        public int ID { get; set; }
        public int CustomerID { get; set; }
        public string ItemScription { get; set; }
    }
}

//上述示例使用了SelectMany的一个重载版本
//public static IEnumerable<TResult> SelectMany<TSource,TResult>(this IEnumerable<TSource> source,Func<TSource,int,TResult> selector)
//{
//    //...
//}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值