平面数据分层模型C# [英] Flat Data to Hierarchical Model C#
问题描述
List< FlatDataGroup>< p> elements = new List ()
{
新FlatDataGroup {Text =,GroupID = 1,ParentGroupID = 0,GroupName =Admin,UserID = 1,UserName =John Doe },
New FlatDataGroup {Text =,GroupID = 1,ParentGroupID = 0,GroupName =Admin,UserID = 2,UserName =Jane Smith},
New FlatDataGroup {Text = ,GroupID = 2,ParentGroupID = 1,GroupName =Support,UserID = 3,UserName =Johnny Support},
新FlatDataGroup {Text =,GroupID = 3,ParentGroupID = 2,GroupName = SubSupport,UserID = 4,UserName =Sub Johnny Support},
FlatDataGroup {Text =,GroupID = 4,ParentGroupID = 1,GroupName =Production,UserID = 5,UserName = Johnny Production}
};
我想将其转换为:
列表与LT;组> model = new List< Group>
{
new Group()
{
ID = 1,
Name =Admin,
ParentGroupID = 0,
Type = Group,
Users = new List< User>()
{
new User()
{
ID = 1,
Name = John Doe,
GroupID = 1,
Type =User,
},
新用户()
{
ID = 2,
Name =Jane Smith,
GroupID = 1,
Type =User,
},
},
Groups = new List< Group> ;
{
新集团()
{
ID = 2,
名称=支持,
ParentGroupID = 1,
类型= Group,
Users = new List< User>()
{
new User()
{
ID = 3,
Name = Johnny Support,
GroupID = 2,
Type =User,
}
},
Groups = new List< Group>()
{
新集团()
{
ID = 3,
Name =SubSupport,
ParentGroupID = 2,
Type =Group,
Users = new List< User>()
{
新用户()
{
ID = 4,
Name =Sub Johnny Support,
GroupID = 3,
Type =User ,
}
},
Groups = null
}
}
},
new Group()
{
ID = 4,
Name =Production,
ParentGroupID = 1,
Type =Group,
Users = new List< User>()
{
新用户()
{
ID = 5,
名称=Johnny Production,
GroupID = 4,
Type =User ,
}
},
Groups = null
}
}
}
};
最终会在treeview中显示如下:
$ b $ (用户)
&Admins(Group)
Jane Smith(User )
+ Support(Group)
Johnny Support(User )
+ SubSupport(Group)
Sub Johnny支持(用户)
+ Production(Group)
  ; Johnny Production(用户)
到目前为止,将数据输入到上面的模型中:
列表< Group> model = new List< Group>();
var parentGrouping = elements.GroupBy(x => x.ParentGroupID);
foreach(parentGrouping中的var parentGroup)
{
var grouping = parentGroup.GroupBy(y => y.GroupID);
foreach(var group in grouping)
{
Group groupItem = new Group()
{
ID = group.FirstOrDefault()。GroupID,
Name = group.FirstOrDefault()。GroupName,
ParentGroupID = group.FirstOrDefault()。ParentGroupID,
Type =Group,
Users = new List< User>( )
};
foreach(var用户在组中)
{
groupItem.Users.Add(新用户()
{
ID = user.UserID,
Name = user.UserName,
GroupID = user.GroupID,
Type =User,
});
}
model.Add(groupItem);
我的所有群组都与他们的子女用户一起出现,但该层次不被保留。我想我可能需要递归地做这件事,但我似乎无法摆脱它的困扰。任何帮助将不胜感激。
以下是完整性模型:
public class FlatDataGroup
{
public string Text {get;组; }
public int GroupID {get;组; }
public int ParentGroupID {get;组; }
public string GroupName {get;组; }
public int UserID {get;组; }
public string UserName {get;组; }
}
public class Group
{
public int ID {get;组; }
public int ParentGroupID {get;组; }
public string Name {get;组; }
公共列表< Group>组{get;组; }
public List< User>用户{get;组; }
public string Type {get;组; }
}
public class User
{
public int ID {get;组; }
public int GroupID {get;组; }
public string Name {get;组; }
public string Type {get;组; }
}
3遍:
-
创建所有
群组类并填充它们以外的数据,将它们递增添加到将字段映射到组的字典中。
循环浏览字典中的所有组并将孩子添加到他们父母的
小组
小孩列表中。 返回所有小组的过滤列表没有父组 - 这些是根组。 (我也通过ID对它们进行了排序,以去除字典将要介绍的随机排序。) 因此: p>
public static class FlatDataGroupExtensions
{
public const string UserType =User;
public const string GroupType =Group;
public static List< Group> ToGroups(这个IEnumerable< FlatDataGroup>元素)
{
//通过ID分配所有组和索引。
var groups = new Dictionary< int,Group>();
foreach(元素中的var元素)
{
群组;
if(!groups.TryGetValue(element.GroupID,out group))
groups [element.GroupID] =(group = new Group(){ID = element.GroupID,Name = element.GroupName, ParentGroupID = element.ParentGroupID,Type = GroupType});
group.Users.Add(new User(){GroupID = element.GroupID,ID = element.UserID,Name = element.UserName,Type = UserType});
}
//将子组添加到父母。
foreach(var group in groups.Values)
{
组父;
if(groups.TryGetValue(group.ParentGroupID,out parent)&& parent!= group)//第二次检查安全性。
parent.Groups.Add(group);
}
//仅返回按ID排序的根组。
return groups.Values.Where(g =>!groups.ContainsKey(g.ParentGroupID))。OrderBy(g => g.ID).ToList();
我也修改了你的组
有点自动分配列表:
public class Group
{
列表< Group> groups = new List< Group>();
列表<用户> users = new List< User>();
public int ID {get;组; }
public int ParentGroupID {get;组; }
public string Name {get;组; }
public string Type {get;组; }
公共列表< Group>组{获得{返回组; }}
public List< User>用户{获得{返回用户; }}
$ b $ public override string ToString()
{
return string.Format(Group:ID = {0},Name = {1},Parent ID = {2 },#Users = {3},#Groups = {4},ID,Name,ParentGroupID,Users.Count,Groups.Count);
}
}
I have some flat data coming from the database that looks like this:
List<FlatDataGroup> elements = new List<FlatDataGroup>()
{
new FlatDataGroup {Text = "", GroupID = 1, ParentGroupID = 0, GroupName = "Admin", UserID = 1, UserName = "John Doe"},
new FlatDataGroup {Text = "", GroupID = 1, ParentGroupID = 0, GroupName = "Admin", UserID = 2, UserName = "Jane Smith"},
new FlatDataGroup {Text = "", GroupID = 2, ParentGroupID = 1, GroupName = "Support", UserID = 3, UserName = "Johnny Support"},
new FlatDataGroup {Text = "", GroupID = 3, ParentGroupID = 2, GroupName = "SubSupport", UserID = 4, UserName = "Sub Johnny Support"},
new FlatDataGroup {Text = "", GroupID = 4, ParentGroupID = 1, GroupName = "Production", UserID = 5, UserName = "Johnny Production"}
};
I would like to convert it to this:
List<Group> model = new List<Group>
{
new Group()
{
ID = 1,
Name = "Admin",
ParentGroupID = 0,
Type = "Group",
Users = new List<User>()
{
new User()
{
ID = 1,
Name = "John Doe",
GroupID = 1,
Type = "User",
},
new User()
{
ID = 2,
Name = "Jane Smith",
GroupID = 1,
Type = "User",
},
},
Groups = new List<Group>
{
new Group()
{
ID = 2,
Name = "Support",
ParentGroupID = 1,
Type = "Group",
Users = new List<User>()
{
new User()
{
ID = 3,
Name = "Johnny Support",
GroupID = 2,
Type = "User",
}
},
Groups = new List<Group>()
{
new Group()
{
ID = 3,
Name = "SubSupport",
ParentGroupID = 2,
Type = "Group",
Users = new List<User>()
{
new User()
{
ID = 4,
Name = "Sub Johnny Support",
GroupID = 3,
Type = "User",
}
},
Groups = null
}
}
},
new Group()
{
ID = 4,
Name = "Production",
ParentGroupID = 1,
Type = "Group",
Users = new List<User>()
{
new User()
{
ID = 5,
Name = "Johnny Production",
GroupID = 4,
Type = "User",
}
},
Groups = null
}
}
}
};
which will ultimately display like this in a treeview:
+Admin (Group)
John Doe (User)
Jane Smith (User)
+Support (Group)
Johnny Support (User)
+SubSupport (Group)
Sub Johnny Support (User)
+Production (Group)
Johnny Production (User)
This is what I've come up with so far to transform the flat data into the model above:
List<Group> model = new List<Group>();
var parentGrouping = elements.GroupBy(x => x.ParentGroupID);
foreach (var parentGroup in parentGrouping)
{
var grouping = parentGroup.GroupBy(y => y.GroupID);
foreach (var group in grouping)
{
Group groupItem = new Group()
{
ID = group.FirstOrDefault().GroupID,
Name = group.FirstOrDefault().GroupName,
ParentGroupID = group.FirstOrDefault().ParentGroupID,
Type = "Group",
Users = new List<User>()
};
foreach (var user in group)
{
groupItem.Users.Add(new User()
{
ID = user.UserID,
Name = user.UserName,
GroupID = user.GroupID,
Type = "User",
});
}
model.Add(groupItem);
}
}
All my groups come out along with their children users but the hierarchy is not preserved. I think I may need to do this recursively but I can't seem to get my head around it. Any help would be greatly appreciated.
Here are the models for the sake of completeness:
public class FlatDataGroup
{
public string Text { get; set; }
public int GroupID { get; set; }
public int ParentGroupID { get; set; }
public string GroupName { get; set; }
public int UserID { get; set; }
public string UserName { get; set; }
}
public class Group
{
public int ID { get; set; }
public int ParentGroupID { get; set; }
public string Name { get; set; }
public List<Group> Groups { get; set; }
public List<User> Users { get; set; }
public string Type { get; set; }
}
public class User
{
public int ID { get; set; }
public int GroupID { get; set; }
public string Name { get; set; }
public string Type { get; set; }
}
I'd do this in 3 passes:
Create all
Group
classes and populate them with data other than child groups, adding them incrementally to a dictionary mapping ID to Group.Loop through all the groups in the dictionary and add children to their parents'
Groups
list of children.Return a filtered list of all groups with no parent group -- these are the root groups. (I also sorted them by ID to remove the random ordering that the dictionary will introduce.)
Thus:
public static class FlatDataGroupExtensions
{
public const string UserType = "User";
public const string GroupType = "Group";
public static List<Group> ToGroups(this IEnumerable<FlatDataGroup> elements)
{
// Allocate all groups and index by ID.
var groups = new Dictionary<int, Group>();
foreach (var element in elements)
{
Group group;
if (!groups.TryGetValue(element.GroupID, out group))
groups[element.GroupID] = (group = new Group() { ID = element.GroupID, Name = element.GroupName, ParentGroupID = element.ParentGroupID, Type = GroupType });
group.Users.Add(new User() { GroupID = element.GroupID, ID = element.UserID, Name = element.UserName, Type = UserType });
}
// Attach child groups to their parents.
foreach (var group in groups.Values)
{
Group parent;
if (groups.TryGetValue(group.ParentGroupID, out parent) && parent != group) // Second check for safety.
parent.Groups.Add(group);
}
// Return only root groups, sorted by ID.
return groups.Values.Where(g => !groups.ContainsKey(g.ParentGroupID)).OrderBy(g => g.ID).ToList();
}
}
I also modified your Group
class a little to automatically allocate the lists:
public class Group
{
List<Group> groups = new List<Group>();
List<User> users = new List<User>();
public int ID { get; set; }
public int ParentGroupID { get; set; }
public string Name { get; set; }
public string Type { get; set; }
public List<Group> Groups { get { return groups; } }
public List<User> Users { get { return users; } }
public override string ToString()
{
return string.Format("Group: ID={0}, Name={1}, Parent ID={2}, #Users={3}, #Groups={4}", ID, Name, ParentGroupID, Users.Count, Groups.Count);
}
}
这篇关于平面数据分层模型C#的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!