2015-03-19 86 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

相关问题