我有一个List(.NET),需要构建一个缩进的树结构。列表中的每个项目都有一个Position属性,指示缩进级别。最终结构应如下所示:
// (1) 1
// (2) 1-1
// (2) 1-2
// (2) 1-3
// (1) 2
// (2) 2-1
// (3) 2-1-1
// (1) 3
括号内的数字是Position属性。给定级别的每个后续项目都应该有一个标签,表明该级别的项目列表中的计数。较低的位置级别将具有一种轮廓格式标签,如示例中所示。请记住,我必须正确生成这些标签。
老实说,我已经做了一段时间的递归工作,尽管我认为这将是最好的解决方案,但我只是坚持如何完成工作。我可能过于复杂了。我的想法是,当我到达一片叶子时,"我应该从列表中删除该项目并返回,但我不确定。只是旋转我的车轮。
谢谢, 杰
更新
这里有些接近,但我在查明最后一个案例时遇到了麻烦。到目前为止,如果下一个项目落在同一级别或缩进一个级别,它会很好,但我需要一个案例,当列表中的下一个项目位于小于当前项目的位置时(即,缩进到更远的位置)左边)。另外,我不确定该方法顶部的基本情况:
var sb = new StringBuilder();
BuildTree(sb, list, 0, 1, string.Empty);
return sb.ToString();
private void BuildTree(StringBuilder sb, List<Item> list, int currIndex, int count, string parentId)
{
if (list.Count == currIndex)
{
return;
}
// Build my item.
string currId = parentId == string.Empty ? count.ToString() : parentId + "-" + count;
sb.Append(currId + "<br />");
if (list[currIndex + 1].Position == list[currIndex].Position)
{
BuildTree(sb, list, currIndex + 1, count + 1, parentId);
}
if (list[currIndex + 1].Position > list[currIndex].Position)
{
BuildTree(sb, list, currIndex + 1, 1, currId);
}
}
更新
另一种实现,但对于较少缩进行的情况仍然失败:
private void BuildTree(StringBuilder sb, List<Item> list, int currIndex, int count, string parentId)
{
if (list.Count == 0)
{
return;
}
// Build my item.
string currId = parentId == string.Empty ? count.ToString() : parentId + "-" + count;
sb.Append(currId + "<br />");
if (list[currIndex + 1].Position == list[currIndex].Position)
{
BuildTree(sb, list, currIndex + 1, count + 1, parentId);
}
if (list[currIndex + 1].Position > list[currIndex].Position)
{
BuildTree(sb, list, currIndex + 1, 1, currId);
}
list.RemoveAt(currIndex);
}
更新
这是一个黑客攻击,但它确实有效。我基本上是在根下构建多个子树。我更喜欢一个合适的解决方案,而不是一个黑客,但这是我迄今为止最好的尝试。欢迎替代方案:
var sb = new StringBuilder();
List<Person> list = GetTheList();
int cnt = 0;
while (list.Count > 0)
{
BuildTree(sb, list, 0, ++cnt, string.Empty);
}
return sb.ToString();
private void BuildTree(StringBuilder sb, List<Person> list, int currIndex, int count, string parentId)
{
// Build my item.
string currId = parentId == string.Empty ? count.ToString() : parentId + "-" + count;
sb.Append(currId + "<br />");
if (list.Count > 1)
{
if (list[currIndex + 1].Position == list[currIndex].Position)
{
BuildTree(sb, list, currIndex + 1, count + 1, parentId);
}
if (list[currIndex + 1].Position > list[currIndex].Position)
{
BuildTree(sb, list, currIndex + 1, 1, currId);
}
}
list.RemoveAt(currIndex);
}
答案 0 :(得分:0)
这是一个选项。它没什么特别的,也许甚至不是很漂亮,并且肯定没有任何健全性检查或错误处理逻辑,但它支持你所说明的结构。
输出应该与您在问题顶部的输出类似,并且它有望引导您朝着正确的方向前进。
using System;
using System.Collections.Generic;
namespace ConsoleApplication1
{
public class Program
{
private static readonly IndentedList indentedList = new IndentedList();
static void Main()
{
Fill();
indentedList.Items.ForEach(Print);
}
private static void Fill()
{
indentedList.Add(new Node()); // 1
indentedList.Add(new Node()); // 2
indentedList.Add(new Node()); // 3
indentedList.Items[0].Add(new Node()); // 1-1
indentedList.Items[0].Add(new Node()); // 1-2
indentedList.Items[0].Add(new Node()); // 1-3
indentedList.Items[1].Add(new Node()); // 2-1
indentedList.Items[1].Children[0].Add(new Node()); // 2-1-1
}
private static void Print(Node node)
{
var indentation = new String('\t', node.IndentationLevel - 1);
Console.WriteLine("{0}({1}) {2}", indentation, node.IndentationLevel, node);
node.Children.ForEach(Print);
}
}
public class IndentedList
{
private readonly Node superNode = new Node();
public List<Node> Items { get { return superNode.Children; } }
public void Add(Node node)
{
superNode.Add(node);
}
}
public class Node
{
public int IndentationLevel { get { return parent == null ? 0 : parent.IndentationLevel + 1; } }
public int Position { get { return parent.Children.IndexOf(this) + 1; } }
public List<Node> Children { get; private set; }
private Node parent;
private bool IsRootNode { get { return parent.parent == null; } }
public Node()
{
Children = new List<Node>();
}
public void Add(Node child)
{
child.parent = this;
Children.Add(child);
}
public override string ToString()
{
return IsRootNode ? Position.ToString() : String.Format("{0}-{1}", parent, Position);
}
}
}
答案 1 :(得分:0)
var sb = new StringBuilder();
List<Person> list = GetTheList();
int cnt = 0;
// The loop is necessary to iterate over the root elements.
while (list.Count > 0)
{
BuildTree(sb, list, 0, ++cnt, string.Empty);
}
return sb.ToString();
private void BuildTree(StringBuilder sb, List<Person> list, int currIndex, int count, string parentId)
{
string currId = parentId == string.Empty ? count.ToString() : parentId + "-" + count;
sb.Append(currId + "<br />");
if (list.Count > 1)
{
if (list[currIndex + 1].Position == list[currIndex].Position)
{
BuildTree(sb, list, currIndex + 1, count + 1, parentId);
}
if (list[currIndex + 1].Position > list[currIndex].Position)
{
BuildTree(sb, list, currIndex + 1, 1, currId);
}
}
list.RemoveAt(currIndex);
}