0

My problem is like Recursive reading of List. However, I have to return a string instead of void. When another method calls it, it would return the formatted string.

I am stuck on formatting the string with indent and how to make this recursive.

public class Name
{
    public string FirstName { get; set; }
}

The return value should look like the list below.

  • Jane Doe
    • Ted Smith
      • Bob Jones
  • Mary Fairchild
    • J. B. Fletcher
Abegail
  • 1
  • 2
  • 3
    Please put your requirements and expected output in your question. We should not have to read other questions to understand yours. – Dour High Arch Aug 19 '18 at 19:01

5 Answers5

0

The first problem I can see with this method is that it has no exit path, Every recursive method needs to have one. That path defines the expected output on the last item of the stack. If you expand more on your desired output, it should be straighforward to write the path

PiJei
  • 584
  • 4
  • 19
0
    public void PrintEmployeeHierarchy(List<Employee> nestedEmployees, ref string result)
    {
        foreach (Employee employee in nestedEmployees)
        {
            if (employee.Subordinates != null && employee.Subordinates.Count > 0)
            {
                PrintEmployeeHierarchy(employee.Subordinates, ref result);
            }
            result += string.Format("{0} {1} {2}", employee.FirstName, employee.LastName, "\t");
        }
    }

Call like :

  string data = "";
  PrintEmployeeHierarchy(empList, ref data);
0

As this could be an indefinitely deep structure, you should opt to use an iterative approach rather than a recursive approach. This will, as a result, keep you from hitting a Stack Overflow Exception. You should use the stack data structure for this..

Writing the solution to this would be somewhat extensive with iteration. However, if this is for an enterprise solution where you need to be able to use an indefinite depth in a production environment, then recursion is typically a bad practice.

If this is personal work and won't be super deep, then it should work fine using Valeh's solution.

AotN
  • 548
  • 2
  • 11
0

You can use a `ref-parameter to makes the same result string accessible throughout all nestings.

I would override ToString in Employee to make printing easier:

public class Employee
{
    public string FirstName { get; set; }
    public string LastName { get; set; }
    public List<Employee> Subordinates { get; set; }

    public override string ToString()
    {
        return $"{FirstName} {LastName}";
    }
}

Using this helper method

private static string Indent(int nestingLevel)
{
    return new string(' ', 4 * nestingLevel);
}

The hierarchy can be printed like this

public void GetEmployeeHierarchy(List<Employee> employees, int level, ref string result)
{
    foreach (Employee emp in employees) {
        result += $"{Indent(level)}- {emp}\r\n";
        GetEmployeeHierarchy(emp.Subordinates, level + 1, ref result);
    }
}

Note that I added a level parameter which is used to determine the indentation. I also renamed the method, as it does not print anything.

Using an appropriate list setup this code

string result = null;
GetEmployeeHierarchy(emps, 0, ref result);
Console.WriteLine(result);
Console.ReadKey();

prints this on my console (also tried the bullet , but it does not print on the console):

- Jane Doe
    - Ted Smith
        - Bob Jones
- Mary Fairchild
    - J.B. Fletcher
Olivier Jacot-Descombes
  • 104,806
  • 13
  • 138
  • 188
0

A modified Employee class that exposes two methods to query an employee subordinates.
Uses recursion in slightly different way.
The lists are ordered by FirstName then LastName.

One method returns only the direct subordinates:
public string GetDirectSubordinates()

The other one returns all subordinates in a hierarchical representation:
public string GetAllSubordinates()

public class Employee
{
    StringBuilder sb = null;
    public Employee(): this("", "") { }
    public Employee(string Firstname, string Lastname)
    {
        this.sb = new StringBuilder();
        this.Subordinates = new List<Employee>();
        this.FirstName = Firstname;
        this.LastName = Lastname;
    }

    public string FirstName { get; set; }
    public string LastName { get; set; }
    public List<Employee> Subordinates { get; set; }

    public string GetDirectSubordinates()
    {
        if (this.Subordinates == null) return string.Empty;
        return string.Join(Environment.NewLine, Subordinates
                     .OrderBy(s => s.LastName).ThenBy(s => s.FirstName)
                     .Select(se => '\t' + se.ToString()));
    }
    public string GetAllSubordinates()
    {
        sb.Append(this.ToString() + " Subordinates:" + Environment.NewLine);
        return GetSubordinateList(1);
    }

    private string GetSubordinateList(int SubLevel)
    {
        foreach (Employee Subordinate in this.Subordinates.OrderBy(sb => sb.FirstName).ThenBy(sb => sb.LastName))
        {
            sb.Append(new string('\t', SubLevel) + ((SubLevel == 1) ? "• " : "– ") + Subordinate.ToString() + Environment.NewLine);
            if (Subordinate.Subordinates != null && Subordinate.Subordinates.Count > 0)
            {
                sb.Append(Subordinate.GetSubordinateList(SubLevel + 1) + Environment.NewLine);
            }
        }
        string result = sb.ToString();
        sb.Clear();
        return result;
    }
    public override string ToString() => $"{this.FirstName} {this.LastName}";
}

Assign some Employees values and add some of them as subordinates and sub-subordinates:

Employee Director = new Employee("John", "McDir");

Employee SubDirector1 = new Employee("Jane", "Doe");
Employee SubDirector2 = new Employee("Mary", "Fairchild");

Employee CoSub1 = new Employee("Ted", "Smith");
Employee CoSub2 = new Employee("Bob", "Jones");
Employee CoSub3 = new Employee("J. B.", "Fletcher");
Employee CoSub4 = new Employee("Larry", "VanLast");

Employee Rookie1 = new Employee("Mick", "Fresh");
Employee Rookie2 = new Employee("Hugh", "DeGreen");
Director.Subordinates.AddRange(new[] { SubDirector1, SubDirector2} );
SubDirector1.Subordinates.AddRange(new[] { CoSub1, CoSub2 });
SubDirector2.Subordinates.AddRange(new[] { CoSub3, CoSub4 });

CoSub3.Subordinates.Add(Rookie1);
CoSub4.Subordinates.Add(Rookie2);

string DirectSubordinates = Director.GetDirectSubordinates(); returns:

Jane Doe
Mary Fairchild

string AllSubordinates = Director.GetAllSubordinates(); returns:
(You need a Font that supports Unicode simbols to print the •)

John McDir Subordinates:
        • Jane Doe
                - Bob Jones
                - Ted Smith

        • Mary Fairchild
                - J. B. Fletcher
                        - Mick Fresh
                - Larry VanLast
                        - Hugh DeGreen
Jimi
  • 29,621
  • 8
  • 43
  • 61