2015-03-19 44 views
1

數據表具有以下的列名:轉換數據表的給詞典<字符串,StringBuilder的>

Name, Value, Type, Info 

需要轉換的結構字典

其中name是密鑰(字符串)和其他值將被追加到像StringBuilder那樣的「Value,Type,Info」,然而它有可能具有重複的Name列值,那麼對StringBuilder連續的每個附加值將使用分隔符如?:來描述下一組值。

對於例如:如果數據表的數據是這樣的:

Name, Value, Type, Info 

one  1  a aa 
one  11 b bb 
two  2  c cc 
two  22 dd ddd 
two  222 ee eee 

現在的結果結構應該是這樣的:

Dictionary<String,StringBuilder> detail = new Dictionary<String,StringBuilder> 
{ 
{[one],[1,a,aa?:11,b,bb}, 
{[two],[2,c,cc?:22,dd,ddd?:222,ee,eee} 
} 

這是很容易使用循環來達到相同的,但我是嘗試通過LINQ到做到這一點,所以我想是這樣:

datatable.AsEnumerable.Select(row => 
{ 
    KeyValuePair<String,StringBuilder> kv = new KeyValuePair<String,StringBuilder>(); 

kv.key = row[Name]; 
kv.Value = row[Value]+","+row[Type]+","+row[Info] 

return kv; 
}).ToDictionary(y=>y.Key,y=>y.Value) 

此代碼不照顧repet的itive鍵和附加,可能我需要使用SelectMany來扁平化結構,但是如何在向我提供上面指定的需求的字典時起作用,以便可以將分隔符添加爲現有密鑰的值。任何可以指引我正確方向的指針。

+0

爲什麼'StringBuilder'爲'Value'? – VMAtm 2015-03-19 12:24:03

+0

這是爲了方便附加字符串而不是使用類似String.Join的東西。這將是有效的 – 2015-03-19 12:29:22

+0

@MrinalKamboj您是否打算在創建字典後添加任何內容?如果不是,那麼'StringBuilder'可能不是非常有用的結果類型。另外,不要假設'string.Join'比沒有Bench Benchmark的'StringBuilder'效率低。對於你所知道的'string.Join'使用'StringBuilder'或者更好的東西。 – juharr 2015-03-19 12:51:46

回答

3

編輯:

datatable.AsEnumerable() 
      .GroupBy(r => (string)r["Name"]) 
      .Select(g => new 
      { 
       Key = g.Key, 
       // Preferred Solution 
       Value = new StringBuilder(
          g.Select(r => string.Format("{0}, {1}, {2}", 
             r["Value"], r["Type"], r["Info"])) 
           .Aggregate((s1, s2) => s1 + "?:" + s2))      
       /* 
       //as proposed by juharr 
       Value = new StringBuilder(string.Join("?:", g.Select(r => string.Format("{0}, {1}, {2}", r["Value"], r["Type"], r["Info"])))) 
       */ 
      }) 
      .ToDictionary(p => p.Key, p => p.Value); 
+0

'Value'是一個'StringBuilder',而不是'String'在OP – VMAtm 2015-03-19 12:23:18

+0

有趣的讓我試試這個,它會確保StringBuilder中的最後一個字符串不會得到分隔符「?:」在它之後 – 2015-03-19 12:35:59

+0

@VMAtm使用StringBuilder的全部意義在於所有的字符串連接,這是在'Aggregate'中完成的,所以它可能只是一個'string'這點。除非OP計劃在後期增加更多東西。 – juharr 2015-03-19 12:41:04

3

像這樣的事情應該工作,並避免一些複雜的LINQ,可以讓刺激的調試:

public static Dictionary<string, StringBuilder> GetData(DataTable table) 
{ 
    const string delimiter = "?:"; 
    var collection = new Dictionary<string, StringBuilder>(); 

    // dotNetFiddle wasn't liking the `.AsEnumerable()` extension 
    // But you should still be able to use it here 
    foreach (DataRow row in table.Rows) 
    { 
     var key = (string)row["Name"]; 

     var @value = string.Format("{0},{1},{2}", 
            row["Value"], 
            row["Type"], 
            row["Info"]); 

     StringBuilder existingSb; 

     if (collection.TryGetValue(key, out existingSb)) 
     { 
      existingSb.Append(delimiter + @value); 
     } 
     else 
     { 
      existingSb = new StringBuilder(); 
      existingSb.Append(@value); 
      collection.Add(key, existingSb); 
     } 
    } 

    return collection; 
} 
+1

我喜歡你的解決方案。字典使用自己的值(字符串構建器)來構建自己,因此它應該比我的解決方案更有效一些。 – B0Andrew 2015-03-19 13:41:02

+0

@Cameron正如我的問題中所建議的,我們已經使用您提出的解決方案來實現它了,我想要使用Linq找出解決方案。我目前的代碼幾乎看起來相同:) – 2015-03-19 17:16:28

+0

@MrinalKamboj我看到我發佈答案後,並沒有認爲不必刪除,因爲它提供了一個不是Linq的解決方案。不過,感謝您對我爲什麼不接受我的回答的評論。 :) – Cameron 2015-03-19 19:19:11

相關問題