2014-05-08 2 views
1

Я определяю следующий класс Node для того, чтобы получить отношение родителя/ребенкаПостроить дерево из таблицы

class Node 
{ 
     public int Id { get; set; } 
     public int? ParentId { get; set; } 
     public string Operator { get; set; } 
     public string Sign { get; set; } 
     public Node Parent { get; set; } 
     public IList<Node> Children { get; set; } 

     public Node() 
     { 
      Children = new List<Node>(); 
     } 

     public override string ToString() 
     { 
      //return "Node: " + Operator + " " + Id + " " + string.Join(",", Children.Select(x => x.Id)); 
      return "Node: " + Operator + " " + Id + " " 
      + string.Join(",", Children.Select(x => string.Format("({0}, {1})", x.Sign, x.Id))); 
     } 
} 

У меня есть следующая таблица, как, например

PNLId PNLCode PNLParentId Operator Sign 
0  
49 C 51 + NULL 
50 Z 51 + NULL 
51 Y 107/ NULL 
52 B 107/ NULL 
53 B 108 + NULL 

Я написал следующий скрипт в главная:

var map = new Dictionary<int, Node>(); 
var rootNodes = new List<Node>(); 

foreach (DataRow row in dt.Rows) 
{ 
    int id = Convert.ToInt32(row["PNLId"]); 
    int? parentId = null; 
    if (!row.IsNull("PNLParentId")) 
    { 
     parentId = Convert.ToInt32(row["PNLParentId"]); 
    } 
    string op = Convert.ToString(row["Operator"]); 
    string sign = Convert.ToString(row["Sign"]); 
    map[id] = new Node 
    { 
     Id = id, 
     ParentId = parentId, 
     Operator = op, 
     Sign=sign 

    }; 
} 

foreach (var pair in map) 
{ 
    if (pair.Value.ParentId.HasValue) 
    { 
     var parent = map[pair.Value.ParentId.Value]; 
     pair.Value.Parent = parent; 
     parent.Children.Add(pair.Value); 
     parent.Operator = pair.Value.Operator; 
    } 
    else 
    { 
     rootNodes.Add(pair.Value); 

    } 
} 

В этом случае он будет возвращаться, для PNLParentId 107

[107 Node: + 107 (, 51),(, 52)] 

что неправильно это должно быть

[107 Node:/107 (, 51),(, 52)] 

Как я могу изменить код выше, чтобы построить дерево узлов первой. Затем начните с корневых узлов, копируя оператор из дочерних элементов. Продвижение детей и копирование их детского оператора?

ответ

1

Я исправил код, который вы написали, чтобы построить дерево. Вот некоторые тестовые данные для работы с (у меня нет таблиц базы данных у вас есть):

var map = new Node[] { 
    new Node() { Id=0, ParentId=0, Operator="", Sign=null} 
    ,new Node() { Id=1, ParentId=null, Operator="+", Sign=null} 
    ,new Node() { Id=2, ParentId=3, Operator="+", Sign=null} 
    ,new Node() { Id=3, ParentId=4, Operator="/", Sign=null} 
    ,new Node() { Id=4, ParentId=4, Operator="/", Sign=null} 
    ,new Node() { Id=5, ParentId=1, Operator="+", Sign=null} 
}; 

А вот фиксированный код:

// remove Value 
var rootNodes = new List<Node>(); 
foreach (var pair in map) 
{ 
    if (pair.ParentId.HasValue) 
    { 
     var parent = map[pair.ParentId.Value]; 
     pair.Parent = parent; 
     parent.Children.Add(pair); 
     parent.Operator = pair.Operator; 
    } 
    else 
    { 
     rootNodes.Add(pair);  
    } 
} 

Изменения:

  • Добавлено rootNodes
  • Удалены .Value

После того, как вы запустили его, коллекция rootNodes будет содержать 1 элемент (тот, у которого есть Id = 1), и массив карт будет содержать правильные ссылки на объекты для своих родителей.

Пояснение:

Переменная pair принадлежит к петле foreach и содержит элементы map. Переменная map представляет собой массив объектов Node, который является классом, в котором вы объявили свойство Parent, которое также относится к типу Node.

Переменные типа Node - все типы объектов, а не типы значений, и, следовательно, они не являются собственностью .Value. Но ParentId, который вы объявили, является обнуляемым типом значения, из-за декларацией int? - и всех обнуляемых типов значений (обратите внимание на суффикс ?) имеют .Value свойства: Так ParentId, вы можете получить значение используя ParentId.Value.HasValue для проверки), но не для Parent, который является объектом Node. Node Свойства объекта должны быть доступны непосредственно по их именам свойств.

+0

Зачем снимать. Значения? Я не понял. – user3548593

+0

@ user3548593: Я отредактировал ответ user3615347 и добавил объяснение. Надеюсь, это поможет. – Matt

+0

@ user3548593: Вы можете проверить код из этого ответа в [LinqPad] (http://www.linqpad.net/) (инструмент, который является бесплатным) - просто поместите его в метод 'main()', добавьте ' rootNodes.Dump(); map.Dump(); 'в конце, затем добавьте класс' Node' из вашего вопроса. Если вы запустите пример, вы увидите, что рекурсивная структура создается в окне вывода: одно из преимуществ метода '.Dump()' LinqPad предоставляет! – Matt

Смежные вопросы