c# - Linq Exclude columns in children -
i trying following: given list of dynamic objects perform group using list of columns provided. here's have far:
using newtonsoft.json; private static void main(string[] args) { dynamic[] data = { new { = "a1", b = "b1", c = "c1", d = "d1", e = "e1", f = "f1"}, new { = "a1", b = "b1", c = "c1", d = "d1", e = "e1", f = "f1", g = "g1"}, new { = "a1", b = "b1", c = "c1", d = "d1", e = "e1", h = "h1", = "i1"} }; var newlist = data.groupby(row => new { row.a, row.b, row.c, row.d, row.e }) .select( y => new { = y.key.a, b = y.key.b, c = y.key.c, d = y.key.d, e = y.key.e, children = y.tolist() }); var str = jsonconvert.serializeobject(newlist); console.read(); }
this works per needs. however, want rid of additional columns appear part of children
field. here's output getting str
:
[ { "a":"a1", "b":"b1", "c":"c1", "d":"d1", "e":"e1", "children":[ { "a":"a1", "b":"b1", "c":"c1", "d":"d1", "e":"e1", "f":"f1" }, { "a":"a1", "b":"b1", "c":"c1", "d":"d1", "e":"e1", "f":"f1", "g":"g1" }, { "a":"a1", "b":"b1", "c":"c1", "d":"d1", "e":"e1", "h":"h1", "i":"i1" } ] } ]
what ideally want following:
[ { "a":"a1", "b":"b1", "c":"c1", "d":"d1", "e":"e1", "children":[ { "e":"e1", "f":"f1" }, { "f":"f1", "g":"g1" }, { "h":"h1", "i":"i1" } ] } ]
any suggestions on how can achieved? know there can number of fields common across objects (e.g., a,b,c,d,e) have no control on others (e.g., f, g, h etc.)
you can use expandoobject
class store properties unique each item , reflection select unique properties.
here's why managed scratch in linqpad:
dynamic[] data = { new { = "a1", b = "b1", c = "c1", d = "d1", e = "e1", f = "f1" }, new { = "a1", b = "b1", c = "c1", d = "d1", e = "e1", f = "f1", g = "g1" }, new { = "a1", b = "b1", c = "c1", d = "d1", e = "e1", h = "h1", = "i1" } }; var keyproperties = new[] { "a", "b", "c", "d", "e" }; var newlist = data.groupby(row => new { row.a, row.b, row.c, row.d, row.e }).select( y => new { = y.key.a, b = y.key.b, c = y.key.c, d = y.key.d, e = y.key.e, children = y.select( item => { ienumerable<dynamic> itemprops = item.gettype().getproperties(); list<dynamic> properties = itemprops.where(p => !enumerable.contains(keyproperties, p.name)).tolist(); var result = new expandoobject(); foreach (var property in properties) { var value = property.getvalue(item, null); if (value != null) { ((idictionary<string, object>)result).add(property.name, value); } } return result; }).tolist() }); var str = jsonconvert.serializeobject(newlist);
and result is:
[ { "a": "a1", "b": "b1", "c": "c1", "d": "d1", "e": "e1", "children": [ { "f": "f1" }, { "f": "f1", "g": "g1" }, { "h": "h1", "i": "i1" } ] } ]
edit
to merge elements @ child level need change projection bit.
first of all, select
becomes selectmany
return collection of keyvaluepair<string, object>
subsequently grouped name , concatenated array:
children = y.selectmany(item => { ienumerable<dynamic> itemprops = item.gettype().getproperties(); list<dynamic> properties = itemprops.where(p => !enumerable.contains(keyproperties,p.name)).tolist(); var result = new expandoobject(); foreach(var property in properties) { var value = property.getvalue(item, null); if(value != null) ((idictionary<string, object>)result).add(property.name, value); } return (idictionary<string, object>)result; }).groupby(prop => prop.key, prop => prop.value) .select(g => { var result = new expandoobject(); ((idictionary<string, object>)result).add(g.key, g.toarray()); return result; }) .tolist()
it's not elegant code should work.
Comments
Post a Comment