Как создать идентификатор иерархии - PullRequest
0 голосов
/ 30 августа 2010

Я хотел бы создать метод для генерации идентификатора иерархии, подобный следующему

1.0
 1.1
   1.1.1
   1.1.2
   1.1.3

 1.2
 1.3
2.0
 2.1

есть ли способ сделать это? любая помощь будет высоко оценена.

Ответы [ 2 ]

3 голосов
/ 30 августа 2010

Вот моя быстрая попытка.

Я предполагаю, что вместо 1.0 и 2.0 вы имели в виду просто 1 и 2 соответственно, иначе это было бы противоречиво.

public class HierarchyGenerator
{
    private List<int> levels = new List<int> { 1 };

    public void DownOneLevel()
    {
        levels.Add(1);
    }

    public void UpLevels(int numLevels)
    {
        if (levels.Count < numLevels + 1)
            throw new InvalidOperationException(
                "Attempt to ascend beyond the top level.");

        for (int i = 0; i < numLevels; i++)
            levels.RemoveAt(levels.Count - 1);
        MoveNext();
    }

    public void MoveNext()
    {
        levels[levels.Count - 1]++;
    }

    public string Current
    {
        get
        {
            return new string(' ', (levels.Count - 1) * 2)
                 + string.Join(".", levels.Select(l => l.ToString()));
        }
    }
}

static partial class Program
{
    static void Main()
    {
        var hg = new HierarchyGenerator();
        Console.WriteLine(hg.Current);  // 1
        hg.DownOneLevel();
        Console.WriteLine(hg.Current);  // 1.1
        hg.DownOneLevel();
        Console.WriteLine(hg.Current);  // 1.1.1
        hg.MoveNext();
        Console.WriteLine(hg.Current);  // 1.1.2
        hg.MoveNext();
        Console.WriteLine(hg.Current);  // 1.1.3
        hg.UpLevels(1);
        Console.WriteLine(hg.Current);  // 1.2
        hg.MoveNext();
        Console.WriteLine(hg.Current);  // 1.3
        hg.UpLevels(1);
        Console.WriteLine(hg.Current);  // 2
        hg.DownOneLevel();
        Console.WriteLine(hg.Current);  // 2.1
    }
}
2 голосов
/ 30 августа 2010

Я предполагаю, что ваша иерархия выражается в виде дерева с использованием этого класса:

class Node {
  public Node() { Children = new Node[0]; }
  public String Name { get; set; }
  public IEnumerable<Node> Children { get; set; }
}

Затем вы можете посетить каждый узел дерева, используя этот метод:

void Visit(Node node, Stack<Int32> levels, Action<Node, String> nodeAction) {
  // Generation of hierachyId can be customized here to say use letters.
  var hierarchyId = 
    String.Join(".", levels.Reverse().Select(l => l.ToString()).ToArray());
  nodeAction(node, hierarchyId);
  var i = 1;
  foreach (var child in node.Children) {
    levels.Push(i++);
    Visit(child, levels, nodeAction);
    levels.Pop();
  }
}

Этот код будет посещать каждый узел дерева в глубине первого порядка, включая корень. Однако в корне будет пустой hierarchyId. Чтобы начать посещение дерева, используйте этот код:

Visit(
  root,
  new Stack<int>(),
  (node, hierarchyId) => Console.WriteLine(hierarchyId + ": " + node.Name)
);

Действие просто запишет имя узла и сгенерированный идентификатор иерархии в консоль.

Вот некоторые примеры данных:

var root = new Node {
  Name = "Root",
  Children = new[] {
    new Node {
      Name = "A",
      Children = new[] {
        new Node {
          Name = "AA",
          Children = new [] {
            new Node { Name = "AAA" },
            new Node { Name = "AAB" },
            new Node { Name = "AAC" }
          }
        },
        new Node { Name = "AB" },
        new Node { Name = "AC" }
      }
    },
    new Node {
      Name = "B",
      Children = new Node[] {
        new Node { Name = "BA" }
      }
    }
  }
};

При запуске кода в этом дереве в консоль записывается следующее:

: Root
1: A
1.1: AA
1.1.1: AAA
1.1.2: AAB
1.1.3: AAC
1.2: AB
1.3: AC
2: B
2.1: BA
...