问题描述
下面我们为MyLinq添加第二个有用的方法,SelectMany,这个方法的作用是,选取序列中的每个元素,每个元素转换成一个序列,再把这些选取的序列连起来,得到一个整体的序列作为结果输出。我们用SelectMany来遍历交错数组:staticvoidMain(string[]args){int[][]data=newint[][]{newint[]{1,2,3},newint[]{4,5},newint[]{},newint[]{6,7,8,9},newint[]{10}};varresult=data.SelectMany(x=>x);foreach(intiteminresult)Console.WriteLine(item);}我们希望输出12345678910这是代码框架,请完成:publicstaticIEnumerable<TResult>SelectMany<TInput,TResult>(thisIEnumerable<TInput>data,Func<TInput,IEnumerable<TResult>>selector){在此添加代码}完成的代码应该类似这样:publicstaticIEnumerable<TResult>SelectMany<TInput,TResult>(thisIEnumerable<TInput>data,Func<TInput,IEnumerable<TResult>>selector){foreach(TInputitemindata){foreach(TResultxinselector(item)){yieldreturnx;}}}SelectMany可以用来获取两个集合的笛卡尔积,比如说,我们有这样两个数组:string[]colors={"红","黄","蓝","绿"};string[]goods={"衣服","帽子","鞋子"};我们用一种颜色搭配一种东西,一共有多少种组合方式?我们可以用SelectMany实现:varresult=colors.SelectMany(x=>goods.Select(y=>x+y));foreach(stringiteminresult){Console.WriteLine(item);}程序输出如下:红衣服红帽子红鞋子黄衣服黄帽子黄鞋子蓝衣服蓝帽子蓝鞋子绿衣服绿帽子绿鞋子很多时候,我们都会在SelectMany中包含一个Select操作,因为这种情况如此常用,我们再编写一个重载形式,将SelectMany和Select二合一。publicstaticIEnumerable<TResult>SelectMany<TInput,TCollection,TResult>(thisIEnumerable<TInput>data,Func<TInput,IEnumerable<TCollection>>selector,Func<TInput,TCollection,TResult>resultSelector){returndata.SelectMany(x=>selector(x).Select(y=>resultSelector(x,y)));}那么我们可以将调用进一步简化成:varresult=colors.SelectMany(x=>goods,(x,y)=>x+y);下面我们编写第三个方法,where,它的作用是,过滤输入的序列,去掉不符合条件的,将符合条件的元素组成新的序列输出。publicstaticIEnumerable<T>Where<T>(thisIEnumerable<T>data,Func<T,bool>predicate){foreach(Titemindata)if(predicate(item))yieldreturnitem;}我们来调用下:staticvoidMain(string[]args){varprocessNames=System.Diagnostics.Process.GetProcesses().Where(x=>x.PeakPagedMemorySize64>40000000L).Select(x=>x.ProcessName);foreach(stringprocessNameinprocessNames){Console.WriteLine(processName);}}这段代码可以列出当前计算机上运行的进程中占用的峰值内存大于40MB(大约)的进程。它在我的计算机上运行结果如下:Microsoft.Alm.Shared.Remoting.RemoteContainer.dlliexploresvchostMsMpEngexplorersvchostsvchostdevenvSystemWINWORD桌面、Word、VS开发环境“榜上有名”。你也可以用这段代码看看你的计算机上什么程序消耗了很多内存。我们还是用之前的代码举例:staticvoidMain(string[]args){strings=@"1,张三,522,李四,373,王五,47";string[]data=s.Split(newstring[]{"rn"},StringSplitOptions.None);varpeople=data.Select(x=>newPerson(){ID=int.Parse(x.Split(',')[0]),Name=x.Split(',')[1],Age=int.Parse(x.Split(',')[2])});foreach(Personpinpeople){Console.WriteLine(p.Name);}}这段代码不是将输入的字符串转化为Person对象了么,我们现在想知道的是,王五多少岁,怎么写?varresult=people.Where(x=>x.Name=="王五");foreach(Personpinpeople){Console.WriteLine(p.Name);}注意,Where返回的是一个序列,哪怕只找到一个元素。所以不能这么写:Personresult=people.Where(x=>x.Name=="王五");Console.WriteLine(result.Name);如果我们确定查找的元素只有一个(比如根据Name找人),或者找到很多匹配的,但是我们确实只需要一个结果就可以,这么写比较麻烦。我们封装一个First方法来简化上面的代码吧。publicstaticTFirst<T>(thisIEnumerable<T>data){vare=data.GetEnumerator();e.MoveNext();returne.Current;}还记得MoveNext和Current么?如果不记得了,可以复习下。在这里,我们只取第一个结果,就不用foreach了。于是我们可以这样调用了:Personresult=people.Where(x=>x.Name=="王五").First();Console.WriteLine(result.Name);
解决方案
解决方案二:
谢谢楼主分享
解决方案三:
解决方案四:
谢谢楼主分享!
解决方案五:
谢谢楼主分享
解决方案六:
看到中间,已经崩溃了
解决方案七:
谢谢楼主分享
解决方案八:
该回复于2015-08-31 23:54:38被版主删除
解决方案九:
怎么还不更新啊
解决方案十:
精彩啊令人回味无穷
解决方案十一:
楼主怎么不更新了?
解决方案十二:
lz我小白很多地方没看懂我们用一种颜色搭配一种东西,一共有多少种组合方式?我们可以用SelectMany实现:varresult=colors.SelectMany(x=>goods.Select(y=>x+y));比如这里为啥不能写varresult=colors.Select(x=>goods.Select(y=>x+y));
解决方案十三:
写的很好啊。
解决方案十四:
写的很好,为什么没再更新了啊
解决方案十五:
原来是这样的,受益匪浅啊。期待更新。
解决方案:
mark。。留着慢慢看。。期待继续更新。。
解决方案:
该回复于2015-05-31 23:33:07被版主删除
解决方案:
谢谢楼主分享
解决方案:
谢谢分享!太感谢了!受益匪浅!再次感谢!祝身体健康、万事如意!
解决方案:
感谢楼主分享
解决方案:
正好在查linq学习一下
解决方案:
解决方案:
先MARK一下,以后来看
解决方案:
楼主怎么不更新了
解决方案:
mark坐等更新
解决方案:
这个SelectMany介绍的太棒了!还会有更新么?