1

リスト (.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 プロパティです。特定のレベルの後続の各アイテムには、そのレベルのアイテムのリストでのカウントを示すラベルが必要です。サンプルに示すように、下位の位置レベルにはアウトライン形式のラベルがあります。これらのラベルを正しく生成する必要があることに注意してください。

正直なところ、私はしばらく再帰的な作業を行っていません。それが最善の解決策になると考えていますが、仕事を完了する方法にこだわっています。私はそれを過度に複雑にしているかもしれません。「葉」にたどり着いたら、その項目をリストから削除して戻るべきだと思いますが、よくわかりません。車輪を少し回すだけです。

ありがとう、ジェイ

アップデート:

これに近いものがありますが、最後のケースを理解するのに苦労しています。これまでのところ、次のアイテムが同じレベルにあるか、1 レベル インデントされている場合は問題ありませんが、リスト内の次のアイテムが現在の位置よりも低い位置にある (つまり、さらにインデントされている) 場合のケースが必要です。左)。また、メソッドの上部にある基本ケースについてはわかりません。

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);
}
4

2 に答える 2

1
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);
}
于 2012-06-30T20:19:56.880 に答える
0

これが1つのオプションです。それは派手なものではなく、おそらくきれいでもありません。確かに、健全性チェックやエラー処理ロジックはありませんが、説明した構造をサポートしています。

出力は、質問の上部にあるものと同様である必要があります。これにより、正しい方向に進むことができれば幸いです。

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);
        }
    }
}
于 2012-06-23T20:47:46.297 に答える