Don Sopjani
Don Sopjani

Reputation: 19

bug in my Recursive method

I'm having a problem with my recursive method. This method is not behaving as i wish it to behave.

What i am trying to do is to is to get a sorted list of all the categories i have in my database, those lists contains a list of childs named ChildList, and i am trying to make a method that would recursively add right child to the rightful parent.

On 3 levels down it behaves exactly as i want, it adds a Child to the childlist of CategoryViewModel. after that, it tends to make duplicate childs which i dont want it to.

For example, you have

Root - Root has Electronics as child, Electronics has Telephones as child, Telephone has Mobilephones, here is where my recursive method duplicate the child, making 2 Mobilephones, and if i have a category Iphone under Mobilephones it would make 3 Iphone-categorychildrens to each Mobilephone. The Iphone categories doesent have any children and the list is 0. but i bet if it would have, each iphone would have 4 childs of that category.

here is my code

namespace GUI.Controllers
{
public class HomeController : Controller
{
    private readonly IRepository<Category> _repo;
    private static List<CategoryViewModel> _sources;

    public HomeController(IRepository<Category> repo)
    {
        _repo = repo;
    }

    public HomeController()
        : this(new Repository<Category>())
    {
    }

    public ViewResult Index()
   {
       var items = _repo.GetAll().ToList();
       var sortedList = new CategoryViewModel();

       _sources = items.Select(c => new CategoryViewModel
       {
           Id = c.Id,
           Name = c.Name,
           Parent = c.Parent.HasValue ? c.Parent.Value : (Guid?) null,
           Products = c.Product.ToList(),
           ChildList = new List<CategoryViewModel>()
       }).ToList();

       _sources = _sources.OrderBy(o => o.Parent).ToList();

       var root = _sources.First();
       sortedList.Id = root.Id;
       sortedList.Name = root.Name;
       sortedList.Parent = null;
       sortedList.ChildList = _sources.Where(o => o.Parent != null && o.Parent == root.Id).ToList();

       foreach (var l in _sources)
       {
           if(l.Parent == null)
               continue;

           l.ChildList = _sources.Where(o => o.Parent != null && o.Parent == l.Id).ToList();

           if (l.ChildList.Any())
               AddItem(l.ChildList, ref sortedList);
       }

       return View(sortedList);
   }

   private static void AddItem(List<CategoryViewModel> children, ref CategoryViewModel sortedList)
   {
       foreach (var child in children)
       {
          var childs = _sources.Where(o => o.Parent != null && o.Parent == child.Id).ToList();
           foreach (var c in childs)
           {
               child.ChildList.Add(c);
           }

           if (child.ChildList.Any())
               AddItem(child.ChildList, ref sortedList);
       }
   }
}
} 


using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using ClassLibrary.Entities;

namespace GUI.Models
{
    public class CategoryViewModel
    {

        [Required]
        public string Name { get; set; }

        [Required]
        public string SearchString { get; set; }

        public Guid Id { get; set; }

        public Guid? Parent { get; set; }
        public string ParentName { get; set; }

        public List<Product> Products { get; set; } 

        public List<CategoryViewModel> ChildList { get; set; }
    }
}

Upvotes: 1

Views: 206

Answers (1)

Don Sopjani
Don Sopjani

Reputation: 19

Ok i found out what the solution to my problem is;

My recursive method was overflow of code, i went too deep without understanding how to practicly use the recursive method. as they say; one thing led to another and i eventually deleted my AddItem Method, it turns out that my lambda expression sorted out the lists for me in the right collection of lists; the final code looks alot more clean and is alot smaller now;

public ViewResult Index()
   {
       var items = _repo.GetAll().ToList();
       var categories = items.Select(c => new CategoryViewModel
       {
           Id = c.Id,
           Name = c.Name,
           Parent = c.Parent.HasValue ? c.Parent.Value : (Guid?) null,
           Products = c.Product.ToList(),
           ChildList = new List<CategoryViewModel>()
       }).OrderBy(o => o.Parent).ToList();

      var sortedCategories = categories.First();
      sortedCategories.ChildList = categories.Where(o => o.Parent != null && o.Parent == sortedCategories.Id).ToList();

      foreach (var l in categories.Where(l => l.Parent != null))
      {
          l.ChildList = categories.Where(o => o.Parent != null && o.Parent == l.Id).ToList();
      }

       return View(sortedCategories);
   }

Upvotes: 1

Related Questions