Вопрос по list, c#, .net – Рекурсивное чтение списка <Object>

1

У меня есть такая структураList<Object>если быть точным, это "CategoryItem" Объект. Вот мое объявление "CategoryItem" Объект.

public class CategoryItem
{
    public string Name { get; set; }
    public int CategoryID {get; set;}
    public int ParentID {get; set; }
    public List<CategoryItem> SubCategory {get; set;}
}

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

[0] CategoryID: 249
Name: "WelcomeNC"
ParentID: 0
SubCategory: length=4
    [0] CategoryID: 250
        Name: "CNC"
        ParentID: 249
        SubCategory: length=0
    [1] CategoryID: 251
        Name: "Production"
        ParentID: 249
        SubCategory: length=0
    [2] CategoryID: 252
        Name: "Administrative"
        ParentID: 249
        SubCategory: length=1
            [0] CategoryID: 261
                Name: "NPower"
                ParentID: 252
                SubCategory: length=0
    [3] CategoryID: 253
        Name: "Help"
        ParentID: 249
        SubCategory: length=1
            [0] CategoryID: 254
                Name: "7"
                ParentID: 253
                SubCategory: length=1
                    [0] CategoryID: 255
                        Name: "CHLK"
                        ParentID: 254
                        SubCategory: length=0
[1] CategoryID: 111
Name: "First"
ParentID: 0
SubCategory: length=0

Моя проблема в том, как мне войти в каждый элемент CategoryItem. объект мой объявлен:

List<CategoryItem> categoryItems = new List<CategoryItem>();

Так что я могу отобразить его в неупорядоченном списке в HTML, как это

WelcomeNC CNC Production Administrative NPower Help 7 CHLK First

Есть ли способ сделать это?

@ Л.Б .: Да, но ОП сказал, что дерево представляет структуру данных, а не визуализирует ее (в противном случае у него уже есть своего рода рекурсивный алгоритм для построения такого дерева из реляционного источника). Так что я все еще думаю, что у дерева и декларации есть расхождение. abatishchev
Извините, у меня была опечатка ... Я только что исправил свой "CategoryItem" Объект с переменной-членом List & lt; SubCategory & gt; chlkdst

Ваш Ответ

5   ответов
0

рекурсия, Есть довольно много образцов там. Те, что в Википедии, просты, но принцип тот же: решите проблему на одном уровне, затем вызовите тот же методrecursively на каждом подуровне.

1

http://msdn.microsoft.com/en-us/library/7a9swst5(v=vs.80).aspx

The ASP.NET TreeView control is designed to present users with data in a hierarchical structure. Users can open individual nodes that can in turn contain child nodes. The TreeView control is suitable for displaying XML data, but can be used for any data that can be represented in a hierarchy.

Я думаю, что это будет то, что вы хотите.

Иначе, это вопрос итерации каждого элемента в вашем списке и рекурсивной обработки каждого подпункта, который может иметь или не иметь больше подпунктов. Это сложно, но только на первый взгляд.

Позволит ли это мне использовать мою текущую структуру данных & quot; CategoryItem & quot; дано выше, сэр? Я хочу сделать так, чтобы объекты отображались в обычном & lt; ul & gt; и & lt; li & gt; HTML-теги и мой AJAX будут выполнять рендеринг для дерева ... Я следую шаблону MVC 3 с Razor из ASP.NET, сэр chlkdst
1

который "визуализирует" пункт категории. Этим методам необходимо знать уровень или текущую глубину, чтобы откорректировать отступ:

private void RenderCategory(HtmlTextWriter writer, CategoryItem item, int level)
{
  writer.Write("<li style='padding-left: {0}px'>{1}</li>", 
    level * 5,
    HttpUtility.HtmlEncode(item.Name));

  int nextLevel = ++level;
  foreach (CategoryItem child in item.SubCategories)
  { 
    RenderCategory(writer, child, nextLevel);
  }
}
CategoryItem в переданном аргументе не является списком & lt; CategoryItem & gt; объект сэр. Как я передам один CategoryItem, если у меня есть этот объект & quot; List & lt; CategoryItem & gt; categoryItems = новый список & lt; CategoryItem & gt; (); & quot; ? chlkdst
1

в первой версии вопроса), я бы прежде всего построил словарь, в котором каждый идентификатор CategoryID дает вам все элементы подкатегории, а затем рекурсивно распечатал все ваши элементы, используя этот словарь. и начинать с элементов с родительским «0». Предполагая, что Print - это инструкция, которая печатает данные, связанные с вашим элементом, и что он принимает в качестве единственного параметра уровень отступа, код будет выглядеть так:

    public static void PrintItems(List<CategoryItem> items)
    {
        Dictionary<string, List<CategoryItem>> dictOfChildren = new Dictionary<string, List<CategoryItem>>();
        // loop through all the items grouping them according to their ParentID
        foreach (CategoryItem anItem in items)
        {
            List<CategoryItem> children;
            if (!dictOfChildren.TryGetValue(anItem.ParentID, out children))
            {
                children = new List<CategoryItem>();
                dictOfChildren[anItem.ParentID] = children;
            }
            children.Add(anItem);
        }
        // recursively print all the items starting from the ones with ParentID = 0
        // the dictionary is passed to the method in order to be able to find the children of each item
        PrintItems(dictOfChildren["0"], dictOfChildren, 0);
    }

    private static void PrintItems(List<CategoryItem> list, Dictionary<string, List<CategoryItem>> dictOfChildren, int levelOfIndentation)
    {
        foreach (CategoryItem anItem in list)
        {
            // first print the current item
            anItem.Print(levelOfIndentation);
            // then recursively print all its children
            List<CategoryItem> children;
            if (dictOfChildren.TryGetValue(anItem.CategoryID, out children) &&
                children.Count > 0)
                PrintItems(children, dictOfChildren, levelOfIndentation + 1);
        }
    }

Это не совсем объектно-ориентированный, но это должно дать вам подсказку о направлении, которому нужно следовать.

EDIT:

Я видел, что вы отредактировали вопрос и теперь вы добавили свойство SubCategory. Это делает вещи намного проще, и вы можете просто сделать:

public static void PrintItems(List<CategoryItem> items)
{
    // call a recursive method passing 0 as level of indentation
    PrintItems(items, 0);
}

public static void PrintItems(List<CategoryItem> items, int levelOfIndentation)
{
    foreach (CategoryItem anItem in items)
    {
        // print the currentItem
        anItem.Print(levelOfIndentation);
        // increment the level of indentation and callk the same method for the children
        PrintItems(anItem.SubCategory, levelOfIndentation + 1);
    }
}
мой ParentID - это тип int, сэр. Я не понимаю строкового кода dictOfChildren [& quot; 0 & quot;]. Что означает ноль там, сэр? chlkdst
В определении CategoryItem в вашем вопросе ParentID и CategoryID являются строками. В любом случае, вы можете изменить все строки на int. dictOfChildren [& quot; 0 & quot;] (или dictOfChildren [0], если вы используете int) возвращает список CategoryItem с ParentID 0, то есть единиц корневого уровня.
1

не оптимальное, но простое решение будет состоять в том, чтобы просто выполнить итерацию списка и для каждого из элементов, которые вы подсчитываете, сколько раз вы называете его родительский идентификатор, а не 0<li> должен иметь.

Не могли бы вы дать псевдокод для простой визуализации вашей мысли, сэр? Я действительно не имею ни малейшего представления о том, как наступать на все данные на моем объекте ... Как я узнаю, что этот объект имеет 3 уровня глубины подкатегории chlkdst

Похожие вопросы