Reputation: 283
I need a hand to transform my recursive function into a loop as I'm stuck trying to do this for hours. The reason is that I kept running into StackOverflow exception.
Please check the following code:
private List<int> GetManagers(Employee employee, List<Employee> employeeList)
{
List<int> collection = new List<int>();
if (employee.DirectManagers.Any())
{
var managers = employeeList.Where(x => employee.DirectManagers.Any(y => y.Equals(x.Id)));
foreach (var manager in managers)
{
if (!collection.Any(x => x.Equals(manager.Id)))
collection.Add(manager.Id);
if (manager.DirectManagers.Any())
collection.AddRange(GetManagers(manager, employeeList));
}
}
return collection;
}
Edit: More codes here
foreach (var employee in employeeList)
{
List<int> allManagers = new List<int>();
allManagers = GetManagers(employee, employeeList);
// Do something with allManagers found here that does not affect the collection
}
public class Employee
{
public int Id { get; set; }
public int? DepartmentId { get; set; }
public List<int> DirectManagers { get; set; }
public List<int> DirectSubordinates { get; set; }
public int Counter { get; set; }
}
var employeeList = context.AdministratorProfiles
.Where(x => !x.dateResigned.HasValue && x.departmentID.HasValue)
.Select(x => new Employee {
Id = x.id,
DepartmentId = x.departmentID,
Counter = 0,
DirectManagers = x.Managers.Select(y => y.managerID).ToList(),
DirectSubordinates = x.Subordinates.Select(y => y.adminID).ToList()
}).ToList(); // TODO: Add active account here
Basically, what this does is that I'm trying to get all the managers of an Employee. Due to the huge number of staff, I often run into StackOverflow exception. I need a hand, appreciate if anyone out there could lend a hand. Thank you.
Edit: Now, I have listed all the codes. So perhaps you can have a better understanding. Basically, what I'm trying to do is to loop through every single employee to perform work, first I must have a work list. This work list would exclude all the managers or managers' managers to form the final list.
Upvotes: 0
Views: 635
Reputation: 11964
Your problem is not recursion but cyclic references. You can use pattern visitor to work with this problem. (In this pattern you mark all entities that were visited with your recursion method and if you visit this entity again, you just return)
Upvotes: 2
Reputation: 1304
You could do something like:
...
Dictionary<int, bool> processed = new Dictionary<int, bool>();
Queue<Employee> managersQueue = new Queue<Employee>();
managersQueue.Enqueue(employee);
while (managersQueue.Any())
{
var currentEmployee = stack.Dequeue();
var managers = employeeList.Where(x => currentEmployee.DirectManagers.Any(y => y.Equals(x.Id)));
foreach (var manager in managers)
{
if (processed.ContainsKey(manager.Id)) continue;
processed.Add(manager.Id, true);
managersQueue.Enqueue(manager);
}
}
return processed.Select(x => x.Key).ToList();
This is just a basic outline of how you could do this iteratively, obviously I don't know your code base or exactly how certain calls would be made.
Upvotes: 0