2012-11-19 101 views
2

我之前没有做过太多的LINQ,所以我经常会发现一些混淆的方面。最近有人使用GroupBy运算符创建了如下所示的查询。下面是他们做了什么:LINQ和GroupBy

List<int> ranges = new List<int>() {100, 1000, 1000000}; 

List<int> sizes = new List<int>(new int[]{99,98,10,5,5454, 12432, 11, 12432, 992, 56, 222}); 

var xx = sizes.GroupBy (size => ranges.First(range => range >= size)); 

xx.Dump(); 

基本上我作为关键表达式是如何工作的很很困惑,即ranges.First(范围=>范围> =大小

任何人都可以提供一些线索可以吗?提前进一步分解,使这个更容易理解呢?我认为,首先会产生一个结果。

感谢。

回答

3

size => ranges.First(range => range >= size)本功能构建的关键,在这大小将进行分组。这需要电流的大小与发现第一范围,whi ch是更大或相等的当前大小。


工作原理:

对于这>= 99100大小99第一个范围。所以,计算出的关键值将是100。大小与关键100组。

Next sizes 98105也将获得密钥100并转到该组。

对于大小5454计算的按键值是1000000(它是大于5454第一个范围,所以,创建新的密钥,大小去组关键1000000

等等

+1

非常感谢您的解释,它非常有帮助。 – bobbo

3

ranges.First(range => range >= size)返回int,第一range>=当前size值。因此,每大小属于一个范围内。这是基团。

注意,01如果没有给定大小的范围>=,则将抛出异常。

1

如果你写的代码for循环,它看起来是这样的:

var myGroup = new Dictionary<int, List<int>>(); 

foreach(size in sizes) 
{ 
    // ranges.First(range => range >= size) is like bellow 
    range = find minimum value in ranges which is greater than equal to size; 

    // this grouping will be done autamatically by calling GroupBy in your code: 
    if (myGroup[range] has no value) // actually TryGetValue 
     myGroup[range] = new List<int>(); 

    // this addition will be done by each iteration on your inputs. 
    myGroup[range].Add(item); 
} 
在你的LINQ命令

只是不同的是,它不适用与循环,实际上它与哈希表的工作原理,以及它的更快(平均),如果你学习linq,它更具可读性。

0

确实,首先返回一个值,这成为分组的关键。

这里发生的是 - 首先调用每个尺寸值,返回第一个尺寸大于(100,100,100,100,1000000,1000000等)的尺寸。 - “尺寸”按此值分组。对于每个范围都会返回一个分组,例如 100:99,98,10,5,11 ...

1

不能确定它是否增加了透明度,但如果你真的想打破它,你可以做以下的(我猜你正在使用LinqPad)

List<int> ranges = new List<int>() {100, 1000, 1000000}; 
    List<int> sizes = new List<int>(new int[]{99,98,10,5,5454, 12432, 11, 12432, 992, 56, 222}); 

    void Main() 
    { 
     var xx = sizes.GroupBy (size => GetRangeValue(size)); 

     xx.Dump(); 
    } 

    private int GetRangeValue(int size) 
    { 
     // find the first value in ranges which is bigger than or equal to our size 
     return ranges.First(range => range >= size); 
    } 

是的,你是正确的,首先会产生一个结果。

0

GroupBy基本上建立了一个查找表(字典),其中每个符合一种常见的疾病来源中的项目是分组到一个列表,然后在查找表中分配给关键

下面是一个示例程序,它用一个代码块替换您的呼叫到xx.Dump(),该代码块以特定于您的示例的方式漂亮地输出输出。请注意,使用OrderBy可以先对键(范围值)以及与每个范围关联的项目组进行排序。

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

class GroupByDemo 
{ 
    static public void Main(string[] args) 
    { 
     List<int> ranges = new List<int>() {100, 1000, 1000000}; 

     List<int> sizes = new List<int>(
      new int[]{99,98,10,5,5454, 12432, 11, 12432, 992, 56, 222}); 

     var sizesByRange = 
      sizes.GroupBy(size => ranges.First(range => range >= size)); 

     // Pretty-print the 'GroupBy' results. 
     foreach (var range in sizesByRange.OrderBy(r => r.Key)) 
     { 
      Console.WriteLine("Sizes up to range limit '{0}':", range.Key); 

      foreach (var size in range.ToList().OrderBy(s => s)) 
      { 
       Console.WriteLine(" {0}", size); 
      } 
     } 
     Console.WriteLine("--"); 
    } 
} 

预期结果

注意12432,因为该值在原来的源列表中出现两次两次在最后一组出现。

Sizes up to range limit '100': 
    5 
    10 
    11 
    56 
    98 
    99 
Sizes up to range limit '1000': 
    222 
    992 
Sizes up to range limit '1000000': 
    5454 
    12432 
    12432 
--