2015-12-17 49 views
1

我有一組我想要彙總的值的數據集。對於每個組,我想創建一個足夠大的數組來包含最大組的值。當一個組包含小於這個最大數時,我想爲空的鍵值插入一個默認值零。Linq Group中的空組的默認值查詢

數據集

Col1 Col2 Value 
-------------------- 
A  X  10 
A  Z  15 
B  X  9 
B  Y  12 
B  Z  6 

期望的結果

X, [10, 9] 
Y, [0, 12] 
Z, [15, 6] 

注意,值 「A」 在Col1中的數據集具有用於col2的 「Y」 沒有價值。值「A」是外系列中的第一組,因此它是第一個缺失的元素。

以下查詢創建結果數據集,但不插入Y組的默認零值。

result = data.GroupBy(item => item.Col2) 
      .Select(group => new 
      { 
       name = group.Key, 
       data = group.Select(item => item.Value) 
          .ToArray() 
      }) 

實際結果

X, [10, 9] 
Y, [12] 
Z, [15, 6] 

什麼我需要做插入零缺失的羣體價值?

+0

您可以將它放在OLEDB數據表中,而不是在第一步中執行「ToArray」。然後在數據表中,您可以定義要填充的空值,然後將其返回給數組。 – Turo

+0

使'Y'爲'[0,12]'而不是'[12,0]'所需結果的規則是什麼? –

+0

數據是在內存中還是在數據庫中? –

回答

3

這是我如何理解它。

讓我們說我們有這個

class Data 
{ 
    public string Col1, Col2; 
    public decimal Value; 
} 

Data[] source = 
{ 
    new Data { Col1="A", Col2 = "X", Value = 10 }, 
    new Data { Col1="A", Col2 = "Z", Value = 15 }, 
    new Data { Col1="B", Col2 = "X", Value = 9 }, 
    new Data { Col1="B", Col2 = "Y", Value = 12 }, 
    new Data { Col1="B", Col2 = "Z", Value = 6 }, 
}; 

首先,我們需要確定的「固定」部分

var columns = source.Select(e => e.Col1).Distinct().OrderBy(c => c).ToList(); 

然後我們可以用正常的分組處理,但組內我們將左加入columns與組元素,這將允許我們實現所需的行爲

var result = source.GroupBy(e => e.Col2, (key, elements) => new 
{ 
    Key = key, 
    Elements = (from c in columns 
      join e in elements on c equals e.Col1 into g 
      from e in g.DefaultIfEmpty() 
      select e != null ? e.Value : 0).ToList() 
}) 
.OrderBy(e => e.Key) 
.ToList(); 
+0

不錯的一個!這是一個LINQ交叉表查詢btw?我把它作爲'select e!= null? e.Value:0'表達式是什麼使它成爲左連接? –

+1

不是。正如你所看到的,它不是一個單一的LINQ查詢。如果你指的是元素擴展部分,我想這很簡單,左連接概念允許在連接的「右側」包含缺少的匹配項。 –

+1

這是交叉表。是的,'DefaultIfEmpty'加上空檢查的組合組成了所謂的'left outer join' –

1

你可以像下面這樣做: -

int maxCount = 0; 
var result = data.GroupBy(x => x.Col2) 
      .OrderByDescending(x => x.Count()) 
      .Select(x => 
       { 
        if (maxCount == 0) 
         maxCount = x.Count(); 
        var Value = x.Select(z => z.Value); 
        return new 
        { 
         name = x.Key, 
         data = maxCount == x.Count() ? Value.ToArray() : 
           Value.Concat(new int[maxCount - Value.Count()]).ToArray() 
        }; 
       }); 

代碼說明: -

由於需要追加default zeros的情況下,當你在任何一組有較少的項目,我存儲maxCount(任何組可以在變量maxCount中生成),因此我按降序排列項目。接下來,我將存儲項目可以在maxCount變量中產生的最大計數。雖然預測我只是檢查組中的項目數量是否不等於maxCount然後創建大小(maxCount - x.Count)的integer array,即最大數量減去當前組中的項目數並將其附加到數組。

Working Fiddle.

2

這不會是漂亮,但你可以做這樣的事情:

var groups = data.GroupBy(d => d.Col2, d => d.Value) 
       .Select(g => new { g, count = g.Count() }) 
       .ToList(); 
int maxG = groups.Max(p => p.count); 
var paddedGroups = groups.Select(p => new { 
        name = p.g.Key, 
        data = p.g.Concat(Enumerable.Repeat(0, maxG - p.count)).ToArray() }); 
+0

你真的想要按值字段對數據進行分組嗎?這隻會產生沒有Col1的相同數據集,我認爲是按Col2排序的。 –

+1

@PaulTaylor這不是由價值領域分組。在的GroupBy第二拉姆達讓你選擇所得到的值,從而使方法調用的結果是其除去以後'選擇的需要的'IGrouping '的'IGrouping '代替(項目=> item.Value) '。 – Fede

+0

謝謝,這是有用的知道。 –