替换c#树中的单个节点
Replace single node in c# tree
我的应用程序中有一个树结构,其中包含用户的分层数据。
public class User {
//a lot of properties here like Id, Name, Last Name, etc.
public IEnumerable<User> Employees {get;set;}
}
现在我需要用新项目替换这棵树中的某些记录。
var changedUsers = GetChangedUsers();
// Replace all changed user fields in original hierarchy
// (only FirstName, LastName, etc. without touching Employees field)
有什么优雅的方法可以做到这一点吗?
编辑:
我曾尝试使用递归循环,但无法更新记录。
private void ReplaceUserInHierarchy(User modifiedUser, List<User> users)
{
foreach (var user in users)
{
if (user.Id == modifiedUser.Id)
{
//we should update here somehow
return;
}
ReplaceUserInHierarchy(modifiedUser, user.Employees);
}
}
只需更新与给定 ID 匹配的用户:
private void ReplaceUserInHierarchy(User modifiedUser, List<User> users)
{
foreach (var user in users)
{
if (user.Id == modifiedUser.Id)
{
// update properties of user here
user.FirstName = modifiedUser.FirstName;
// etc
return; // if user can be duplicated in hierarchy, then use continue here
}
// assume user cannot be in own employees hierarchy
ReplaceUserInHierarchy(modifiedUser, user.Employees);
}
}
提高优雅度 - 您可以使用扁平化层次结构的扩展方法。然后搜索您应该更新的用户,如下所示:
var user = users.Flatten(u => u.Employees).FirstOrDefault(u => u.Id == modifiedUser.Id);
if (user != null) // you can throw if user not found
user.FirstName = modifiedUser.FirstName; // etc
可以按
进行展平
public static IEnumerable<T> Flatten<T>(
this IEnumerable<T> source,
Func<T, IEnumerable<T>> selector)
{
// null-check arguments
foreach(var item in source)
{
yield return item;
foreach(var child in Flatten(selector(item), selector))
yield return child;
}
}
进一步的改进 - 您可以将扁平化的层次结构保存到字典中并使用它来更新多个用户:
var usersById = users.Flatten(u => u.Employees).ToDictionary(u => u.Id);
foreach(var modifiedUser in modifiedUsers)
{
User user;
if (!usersById.TryGetValue(modifiedUser.Id, out user);)
continue; // or throw
user.FirstName = modifiedUser.FirstName; // etc
}
进一步改进 - 您可以使用像 AutoMapper 这样的库来自动进行映射。
我的应用程序中有一个树结构,其中包含用户的分层数据。
public class User {
//a lot of properties here like Id, Name, Last Name, etc.
public IEnumerable<User> Employees {get;set;}
}
现在我需要用新项目替换这棵树中的某些记录。
var changedUsers = GetChangedUsers();
// Replace all changed user fields in original hierarchy
// (only FirstName, LastName, etc. without touching Employees field)
有什么优雅的方法可以做到这一点吗?
编辑:
我曾尝试使用递归循环,但无法更新记录。
private void ReplaceUserInHierarchy(User modifiedUser, List<User> users)
{
foreach (var user in users)
{
if (user.Id == modifiedUser.Id)
{
//we should update here somehow
return;
}
ReplaceUserInHierarchy(modifiedUser, user.Employees);
}
}
只需更新与给定 ID 匹配的用户:
private void ReplaceUserInHierarchy(User modifiedUser, List<User> users)
{
foreach (var user in users)
{
if (user.Id == modifiedUser.Id)
{
// update properties of user here
user.FirstName = modifiedUser.FirstName;
// etc
return; // if user can be duplicated in hierarchy, then use continue here
}
// assume user cannot be in own employees hierarchy
ReplaceUserInHierarchy(modifiedUser, user.Employees);
}
}
提高优雅度 - 您可以使用扁平化层次结构的扩展方法。然后搜索您应该更新的用户,如下所示:
var user = users.Flatten(u => u.Employees).FirstOrDefault(u => u.Id == modifiedUser.Id);
if (user != null) // you can throw if user not found
user.FirstName = modifiedUser.FirstName; // etc
可以按
进行展平public static IEnumerable<T> Flatten<T>(
this IEnumerable<T> source,
Func<T, IEnumerable<T>> selector)
{
// null-check arguments
foreach(var item in source)
{
yield return item;
foreach(var child in Flatten(selector(item), selector))
yield return child;
}
}
进一步的改进 - 您可以将扁平化的层次结构保存到字典中并使用它来更新多个用户:
var usersById = users.Flatten(u => u.Employees).ToDictionary(u => u.Id);
foreach(var modifiedUser in modifiedUsers)
{
User user;
if (!usersById.TryGetValue(modifiedUser.Id, out user);)
continue; // or throw
user.FirstName = modifiedUser.FirstName; // etc
}
进一步改进 - 您可以使用像 AutoMapper 这样的库来自动进行映射。