Гость
Форумы / WinForms, .Net Framework [игнор отключен] [закрыт для гостей] / Рекурсивно перессоздать дерево из линейно построенного List<T> / 5 сообщений из 5, страница 1 из 1
03.09.2015, 18:48
    #39042795
zalsily
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Рекурсивно перессоздать дерево из линейно построенного List<T>
Добрый день.

Есть тип

Код: c#
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
    public class Category
    {
        public int Id { get; set; }//личный идентификатор
        public int ParentCategoryId { get; set; }//идентификатор родительской категории
        public List<Classes.Category> ChildCategories { get; set; }//контейнер для дочерних категорий

        public Category()
        {

        }
    }



И есть список объектов данного типа:
Код: c#
1.
List<Category> categorylist //содержит 10-20 объектов


Список categorylist содержит объекты, у каждого из которых поле ChildCategories является NULL.
Ну это пока null.

Требуется так перестроить этот список, что бы все дочерние категории переместить в их родительские, при этом глубина вложенности может быть сколь угодно глубокой.

Накрапал рекурсивный метод:

Код: c#
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
foreach(Classes.Category cat in categories)
            this.RepositionItem(categories, cat);

    void RepositionItem(List<Classes.Category> categorylist, Classes.Category category)
    {
        //проходим по списку всех категорий
        for (int i = 0; i < categorylist.Count; i ++ )//foreach приводит к ошибке, в момент удаления элемента из списка
        {
            //если нашли родительскую категорию
            if (category.ParentCategoryId == categorylist[i].Id)
            {
                if (categorylist[i].ChildCategories == null)
                    categorylist[i].ChildCategories = new List<Classes.Category>();

                categorylist[i].ChildCategories.Add(category);
                //categorylist.Remove(category);
                //i--;
            }
            //если в верхнем уровне не нашлось родительской категории
            //возможно она есть в дочернем списке подкатегорий
            else
                if (categorylist[i].ChildCategories != null)
                    RepositionItem(categorylist[i].ChildCategories, category);
        }
    }



И работает ну почти так, как ожидается. Да, все объекты подкатегорий были перенесены в объекты верхних категорий, что и требуется.
Но также эти объекты эти объекты остались на своих местах. Точнее, ссылки остались (тип то ссылочный).

Если изначально categorylist содержал 10 элементов категорий, то после перетасовки, к примеру, должен был содержать только 4 элемента (а внутри которых должны содержаться остальные 6, разбросанные в соответствии).

Если расскомментить строки
//categorylist.Remove(category);
//i--;
то в определенный момент цикл накрывается.

Загвоздка в том, что как правильно удалять перемещаемые элементы из одного места в списке, в другой объект.
...
Рейтинг: 0 / 0
03.09.2015, 19:14
    #39042798
Axeleron
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Рекурсивно перессоздать дерево из линейно построенного List<T>
zalsily,
Понятно, что будут проблемы. Как вариант - собрать все категории для удаления в новую коллекцию, а послед выхода из цикла добавления к верхним категориям пройтись по этой 'собранной' коллекции и поудалять в нижних категориях.
...
Рейтинг: 0 / 0
03.09.2015, 19:23
    #39042803
zalsily
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Рекурсивно перессоздать дерево из линейно построенного List<T>
Axeleron, уже сделал так.

Но, как всегда, обнаружилась другая проблема. Почему то на уровне вложенности 3 и глубже по два раза подподкатегории добавлены.

Наверное надо перед добавление проверку делать на присутствие такого объекта (где-то по несколько раз, видимо, проход получается по одному и тому же номеру спсика, что и тянет несколько раз один и тот же элемент).
...
Рейтинг: 0 / 0
03.09.2015, 19:25
    #39042805
Axeleron
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Рекурсивно перессоздать дерево из линейно построенного List<T>
zalsilyНаверное надо перед добавление проверку делать на присутствие такого объекта (где-то по несколько раз, видимо, проход получается по одному и тому же номеру спсика, что и тянет несколько раз один и тот же элемент).
Это по-любому хорошая идея :)
...
Рейтинг: 0 / 0
04.09.2015, 07:27
    #39043038
bazile
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Рекурсивно перессоздать дерево из линейно построенного List<T>
zalsily, можно обойтись и без рекурсии
Код: c#
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
List<Category> categorylist = new List<Category>();
categorylist.Add(new Category { Id = 1, ParentCategoryId = 0 });
categorylist.Add(new Category { Id = 2, ParentCategoryId = 1 });
categorylist.Add(new Category { Id = 3, ParentCategoryId = 2 });
categorylist.Add(new Category { Id = 4, ParentCategoryId = 1 });
categorylist.Add(new Category { Id = 5, ParentCategoryId = 0 });
Dictionary<int, Category> id2Category = categorylist.ToDictionary(c => c.Id);
foreach (var category in categorylist)
{
    Category parentCategory;
    if (id2Category.TryGetValue(category.ParentCategoryId, out parentCategory))
    {
        if (parentCategory.ChildCategories == null) parentCategory.ChildCategories = new List<Category>();
        parentCategory.ChildCategories.Add(category);
    }
}
categorylist.RemoveAll(c => c.ParentCategoryId != 0);
...
Рейтинг: 0 / 0
Форумы / WinForms, .Net Framework [игнор отключен] [закрыт для гостей] / Рекурсивно перессоздать дерево из линейно построенного List<T> / 5 сообщений из 5, страница 1 из 1
Целевая тема:
Создать новую тему:
Автор:
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]