Remove Object From Hierarchical Collection
c#, linq
Solution
Here a recursive way of doing this:
private void DeleteNode(IList<Node> nodes, Guid id)
{
Node nodeToDelete = null;
foreach (var node in nodes)
{
if (node.Id == id)
{
nodeToDelete = node;
break;
}
DeleteNode(node.Children, id);
}
if (nodeToDelete != null)
{
nodes.Remove(nodeToDelete);
}
}
If you'd like to have all the operations in one loop, do it with a for loop. In my opinion it's much harder to read, though.
private void DeleteNode(IList<Node> nodes, int id)
{
for (var index = 0; index < nodes.Count; index++)
{
var currentNode = nodes[index];
if (currentNode.Id == id)
{
nodes.Remove(currentNode);
break;
}
DeleteNode(currentNode.Children, id);
}
}
Another method would be to have a flat (non-hierarchical) list or even dictionary (quickest way!), which contains all the elements. You could add another property, which contains the Parent ID of the child. In some cases, especially when you have deep trees with lots of items, this way would be much more performant. If you want to remove a certain item, do it like this:
private void DeleteNode(IList<Node> flatNodes, Guid id)
{
var nodeToDelete = flatNodes.FirstOrDefault(n => n.Id == id);
if (nodeToDelete != null)
{
var parent = flatNodes.First(n => n.Id == nodeToDelete.ParentId);
parent.Children.Remove(nodeToDelete);
}
}
private void DeleteNodeFromFlatDictionary(IDictionary<Guid, Node> flatNodes, Guid id)
{
if (!flatNodes.ContainsKey(id)) return;
var nodeToDelete = flatNodes[id];
flatNodes[nodeToDelete.ParentId].Children.Remove(id);
}
If you want the UI to recognize changes you need to use `ObservableCollection<Node>`, though.
Problem
I have a collection of NodeObject classes in a hierarchical list. The list can be any number of levels deep. ``` public class NodeModel : ViewModelBase { public Guid Id { get; set; } public string Caption { get; set; } public string Description { get; set; } public NodeType Type { get; set; } public List<NodeModel> Children { get; set; } } ``` How can I remove an item from the list using its Guid Id regardless of where it is in the list?