c# - 更新树层次结构中的中间节点
问题描述
我有一个包含字符串属性的节点树层次结构。树层次结构包含一个父子级和该子级的一个子级,依此类推。我必须从列表中找到并更新中间孩子之一的字符串属性,并更新父级及其子级。例如,
NodeData[] nodes = new NodeData[]
{
new NodeData
{
Text = "A",
Children = new NodeData[]
{
new NodeData {
Text = "C",
Children = new NodeData[]
{
new NodeData {Text = "AB" }
}
},
new NodeData { Text = "D" },
}
},
new NodeData
{
Text = "B",
Children = new NodeData[]
{
new NodeData
{
Text = "E",
Children = new NodeData[]
{
new NodeData { Text = "F" },
}
}
}
}
};
在这种情况下,我必须找到带有文本“AB”的节点,然后更新节点“AB”,但还要更新具有文本“D”、“C”和“A”的 NodeData。我不知道该怎么做,我想保留一个列表,然后通过该列表运行以更新相关字段。
解决方案
这是我对解决方案的尝试。
给定看起来像这样的树:
A
C
AB
AC
D
B
E
F
并且鉴于需要更新针节点的所有直接兄弟节点和所有父节点(包括它们的兄弟节点),这是我的代码:
using System;
using System.Linq;
namespace Ns
{
internal static class Program
{
private static void Main(string[] args)
{
var nodes = new[]
{
new NodeData("A",
new NodeData("C",
new NodeData("AB"),
new NodeData("AC")),
new NodeData("D")),
new NodeData("B",
new NodeData("E",
new NodeData("F")))
};
FindAndUpdateAscendingly(nodes, "AB", x => Console.WriteLine(x.Text));
}
private static void FindAndUpdateAscendingly(NodeData[] rootNodes, string dataToFind, Action<NodeData> callback)
{
bool FindAndAscend(NodeData[] nodes)
{
var needleIsFound = nodes.Any(x => x.Text == dataToFind || FindAndAscend(x.Children));
if (needleIsFound)
{
foreach (var nodeData in nodes)
{
callback(nodeData);
}
}
return needleIsFound;
}
FindAndAscend(rootNodes);
}
}
internal class NodeData
{
public NodeData(string text, params NodeData[] children)
{
Text = text;
Children = children ?? Array.Empty<NodeData>();
}
public string Text { get; }
public NodeData[] Children { get; }
}
}
它的要点在于FindAndUpdateAscendingly
函数。您将一个节点数组传递给它,一个您想要查找的字符串,以及一个您想要在您想要更新的每个节点上调用的函数。
目前,我将 aConsole.WriteLine
作为假的“更新”函数传递,只是为了说明迭代顺序。这是打印的节点迭代顺序:
AB
AC
C
D
A
B
基本上,它使用您指定的文本搜索节点,然后冒泡并调用callback
所有父节点及其兄弟节点。这就是为什么你不触摸E
和F
节点。
对于真实数据和实际使用,Console.WriteLine
您将传递一个实际上对 NodeData 做了某些事情的函数,而不是传递 。例如,像这样:
FindAndUpdateAscendingly(nodes, "AB", node =>
{
node.Text += " - processed";
Console.WriteLine(node.Text);
});