【笔记】【LINQ编程技术内幕】第十章 掌握Select 和 SelectMany

    技术2022-07-11  101

    带有函数调用功能的 Select

    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; /* prohibitively slow */ //var primes = from n in numbers // where IsPrime(n) // select n; // use Sieve of Eratosthenes; of course now we have primes 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}", Elapsed(start, stop)); } /// <summary> /// Brute force prime tester, very slow. /// </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; } /// <summary> /// Use the Sieve of Eratosthenes: no number is divisible /// by a number greater than its square root /// </summary> /// <param name="v"></param> /// <returns></returns> 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 = 2; i <= max; i++) { if (IsPrime2(i)) Primes.Add(i); } } /// <summary> /// Recursive Euclidean algorithm /// </summary> /// <param name="num"></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); } private static string Elapsed(DateTime start, DateTime stop) { TimeSpan span = stop - start; return string.Format("Days: {0}, Hours: {1}, Minutes: {2}, Seconds: {3}, Mils: {4}", span.Days, span.Hours, span.Minutes, span.Seconds, span.Milliseconds); } }

    使用 Select 谓词

    var numbers = new int[] { 1, 2, 3, 4, 5, 6, 7, 8, 9 }; var toEvens = from num in numbers select num * 2; Array.ForEach(toEvens.ToArray(), n => Console.WriteLine(n));

    投影新的对象

    var numbers = new int[] { 1, 2, 3, 4, 5, 6, 7, 8, 9 }; var toEvens = numbers.Select(n => new {Number = n}); Array.ForEach(toEvens.ToArray(), n => Console.WriteLine(n));

    使用 Select 的索引打乱数组

    int[] cards = new int[52]; Random rand = new Random(); var shuffler = cards.Select((num, index) => new {Key = index, Random = rand.Next()}); Array.ForEach(shuffler.OrderBy(s=>s.Random).ToArray(), s => Console.WriteLine(s));

    从多个源中投影新类型

    class Program { public class Customer { public int ID { get; set; } public string CompanyName { get; set; } } public class Order { public int ID { get; set; } public int CustomerID { get; set; } public string ItemDescription { get; set; } } static void Main(string[] args) { // explicit select many combines the two sub-arrays string[] words = new string[] { "many have the will to win", "few have the will to prepare" }; var words2 = words.SelectMany(str => str.Split(' ')); Array.ForEach(words2.ToArray(), s => Console.WriteLine(s)); List<Customer> customers = new List<Customer> { new Customer{ID=1, CompanyName="Tom's Toffees"}, new Customer{ID=2, CompanyName="Karl's Coffees"} }; List<Order> orders = new List<Order> { new Order{ID=1, CustomerID=1, ItemDescription="Granulated Sugar"}, new Order{ID=2, CustomerID=1, ItemDescription="Molasses"}, new Order{ID=3, CustomerID=2, ItemDescription="French Roast Beans"}, new Order{ID=4, CustomerID=2, ItemDescription="Ceramic Cups"} }; // implicit select many var orderInfo = from customer in customers from order in orders where customer.ID == order.CustomerID select new { Name = customer.CompanyName, Item = order.ItemDescription }; Array.ForEach(orderInfo.ToArray(), o => Console.WriteLine("Company: {0}, Item: {1}", o.Name, o.Item)); } }

    使用SelectMany从多个序列中创建出一个新序列

    var localMachineKeys = Registry.LocalMachine.OpenSubKey("Software").GetSubKeyNames(); var userKeys = Registry.CurrentUser.OpenSubKey("Software").GetSubKeyNames(); // keys in common var commonKeys = from machineKey in localMachineKeys where machineKey.StartsWith("A") from userKey in userKeys where userKey.StartsWith("A") && machineKey == userKey select machineKey; Array.ForEach(commonKeys.ToArray(), key => Console.WriteLine(key));

    在SelectMany中使用索引

    class Program { public class Customer { public int ID { get; set; } public string CompanyName { get; set; } } public class Order { public int ID { get; set; } public int CustomerID { get; set; } public string ItemDescription { get; set; } } static void Main(string[] args) { List<Customer> customers = new List<Customer> { new Customer{ID=1, CompanyName="Tom's Toffees"}, new Customer{ID=2, CompanyName="Karl's Coffees"} }; List<Order> orders = new List<Order> { new Order{ID=1, CustomerID=1, ItemDescription="Granulated Sugar"}, new Order{ID=2, CustomerID=1, ItemDescription="Molasses"}, new Order{ID=3, CustomerID=2, ItemDescription="French Roast Beans"}, new Order{ID=4, CustomerID=2, ItemDescription="Ceramic Cups"} }; var orderInfo = customers.SelectMany((customer, index) => from order in orders where order.CustomerID == customer.ID select new { Key = index + 1, Customer = customer.CompanyName, Item = order.ItemDescription }); Array.ForEach(orderInfo.ToArray(), o => Console.WriteLine("Key: {0}, Name: {1}, Item: {2}", o.Key, o.Customer, o.Item)); } }
    Processed: 0.011, SQL: 9