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

带有函数调用功能的 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));
	}
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

zhy29563

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值