2012-11-19 102 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 
--