DataTable具有以下列名称:
Name, Value, Type, Info
需要转换结构词典
其中Name是Key(字符串),其他值将附加到StringBuilder,如" Value,Type,Info"但是可以有重复的Name列值,然后连续每个附加值StringBuilder将使用像?:这样的分隔符来描述下一组值。
例如:如果DataTable数据如下:
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}
}
使用for循环很容易实现相同,但我试图通过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)
这段代码没有处理重复的键并因此附加,可能我需要使用SelectMany来展平结构,但是如何在给我一个上面指定的要求的字典时这样做,这样分隔符就可以了添加为现有密钥的值。任何可以指引我正确方向的指针。
答案 0 :(得分: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);
答案 1 :(得分: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;
}