Sunday, May 06, 2007

LINQ,Select 与 SelectMany 的比较(Select vs. SelectMany)

4.3         Select SelectMany 的比较(Select vs. SelectMany


Select 操作符需要转换函数(transform function)用来为信息源序列(source sequence)中的每一个值(each value)产生一个值(produce one value)。如果你的转换函数返回了一个自己也是一个序列的值,它等于(is up to)消费者(consumer)手工地(manually)穿越(traverse)子序列(sub-sequences)。例于,考察下面的程序,使用已存在的 String.Split 方法分拆这些字符串成一段段的部分(breaks strings into tokens):


  


string[] text = { "Albert was here"
                  
"Burke slept late"
                  
"Connor is happy" };

var tokens 
= text.Select(s => s.Split(' '));

foreach (string[] line in tokens)
    
foreach (string token in line)
        Console.Write(
"{0}.", token);


运行这段程序,将打印出如下的文本:


 


Albert.was.here.Burke.slept.late.Connor.is.happy.

 


理想情况下(Ideally),我们希望我们的查询返回一个包含一个个 token 段的结合的序列(coalesced sequence),而不是暴露(exposed)中间的(intermediatestring[] 给消费者(consumer)。为了达到这个目的(To achieve this),我们使用 SelectMany 操作符而不用 Select 操作符。SelectMany 操作符使用起来比 Select 更简单。它们不同的(differs in)地方是转换函数(transform function)被期望返回一个序列,然后才再 SelectMany 操作符展开来(expanded by)。这里是一段我们用 SelectMany 重写的程序:


 


string[] text = { "Albert was here"
                  
"Burke slept late"
                  
"Connor is happy" };

var tokens 
= text.SelectMany(s => s.Split(' '));

foreach (string token in tokens)
    Console.Write(
"{0}.", token);

 


使用 SelectMany 引起每一个中间的序列(each intermediate sequence)像普通赋值的一部分(part of normal evaluation)一样被展开(expanded)。


 


 


 



 


待续, 错误难免,请批评指正,译者Naven 2005-10-24

No comments: