2017-10-11 12 views
-2

J'ai un projet c#, et j'ai créé une classe appelée Employees.
J'ai une nouvelle liste Dans cette classe,:C# défi employé arbre

public class Employees 
{ 
    public int Id { get; set; } 
    public string Name { get; set; } 
    public int? ManagerId { get; set; } 
    public List<Employees> employees { get; set; } 
} 

Imaginez que j'ai la structure suivante montre l'image:
companytree

ensuite dans le programme principal, j'ai cette structure pour représenter l'image ci-dessus:

class Program 
{ 
    static void Main(string[] args) 
    { 
     var root = new Employees() 
     { 
      Id = 15, 
      Name = "President", 
      employees = new List<Employees>() 
      { 
       new Employees() { 

        Id = 23, ManagerId = 15, Name = "Director23", 
        employees = new List<Employees>() 
        { 
         new Employees() { 
          Id = 21, ManagerId = 23, Name = "Manager21", 
          employees = new List<Employees>() 
          { 
           new Employees() { Id = 31, ManagerId=21, Name = "Employee31" }, 
           new Employees() { Id = 41, ManagerId=21, Name = "Employee41" }, 
           new Employees() { Id = 51, ManagerId=21, Name = "Employee51" } 
          } 
         }, 

         new Employees() { 
          Id = 22, ManagerId = 23, Name = "Manager22", 
          employees = new List<Employees>() 
          { 
           new Employees() { Id = 32, ManagerId=22, Name = "Employee32" }, 
           new Employees() { Id = 42, ManagerId=22, Name = "Employee42" }, 
           new Employees() { Id = 52, ManagerId=22, Name = "Employee52" } 
          } 
         } 
        } 
       }, 

       new Employees() { 

        Id = 25, ManagerId = 15, Name = "Director25", 
        employees = new List<Employees>() 
        { 
         new Employees() { 
          Id = 51, ManagerId = 25, Name = "Manager51", 
          employees = new List<Employees>() 
          { 
           new Employees() { Id = 61, ManagerId=51, Name = "Employee61" }, 
           new Employees() { Id = 71, ManagerId=51, Name = "Employee71" }, 
           new Employees() { Id = 81, ManagerId=51, Name = "Employee81" } 
          } 
         }, 

         new Employees() { 
          Id = 62, ManagerId = 25, Name = "Manager62", 
          employees = new List<Employees>() 
          { 
           new Employees() { Id = 72, ManagerId=62, Name = "Employee72" }, 
           new Employees() { Id = 82, ManagerId=62, Name = "Employee82" } 
          } 
         } 
        } 
       } 

      } 
     }; 

     Console.ReadLine(); 
    } 
} 

Comment créer une fonction où je passe la liste des racines de l'arbre de l'employé et l'ID d'un employé de la société et vous devez rendre votre manager plus proche ou plus haut et aussi l'employé lui-même. Rappelez-vous que vous pourriez passer l'identification d'un directeur (vous devrez rendre le président), l'identification du directeur (vous devrez rendre le directeur), l'identification de l'employé (vous devriez retourner le directeur), l'identité du président revient lui-même. Quelle meilleure façon de faire cette recherche en tenant compte du fait que nous pouvons avoir une structure hiérarchique beaucoup plus grande que cet exemple. Il serait coûteux d'analyser toutes les listes.

Utiliser hastable, dictionnaire, hashset ??

+0

Vous devriez travailler sur vos conventions de nommage et boîtier ... 'Employees' ne devrait pas être votre nom de classe, il devrait être 'Employee' (c'est une entité unique). 'employees' devrait être' Subordinates' ou quelque chose qui décrit _actually_ ce que c'est. Ne mélangez jamais le boîtier comme ça. – maccettura

+0

Je suis d'accord avec vous merci, dans la course pour mettre le poste que j'ai commis cette erreur devrait être employé. La structure des classes n'est pas réelle, mais seulement pour démontrer comment nous pourrions faire cette recherche dans cette structure arborescente – devweb

+0

Qu'avez-vous essayé jusqu'à présent? –

Répondre

0

Une fonction récursive est généralement utilisée pour rechercher un arbre. Je suppose que vous fixer les noms de variables comme le suggère:

public static Employee FindById(Employee root, int id) { 
    if (root.Id == id) 
     return root; 
    else if (root.Employees != null) { 
     foreach (var e in root.Employees) { 
      var pe = FindById(e, id); 
      if (pe != null) 
       return pe; 
     } 
    } 
    return null; 
} 

Pour utiliser, trouver l'employé et le gestionnaire:

var emp = FindById(root, 51); 
var manager = emp.ManagerId.HasValue ? FindById(root, emp.ManagerId.Value) : null; 
+0

Oui, j'ai utilisé les noms comme exemple.Votre solution fonctionne, mais je cherche à ne pas lire tous les arbres plus d'une fois, et améliorer la recherche. Je ne sais pas ce que vous pensez de transformer cette liste (arbre) dans un dictionnaire ou HashSet? – devweb

+0

Eh bien, un arbre n'est peut-être pas la bonne structure de données à utiliser dans ce cas. La réponse @DependencyInjection suggère de convertir l'arbre en un 'Dictionary' et de l'utiliser, et bien qu'il manque la vérification d'erreur, le problème principal que je vois est ce qui se passe quand vous mettez à jour l'arbre? – NetMage

0

Ajouter il y a deux fonctions:

public static IDictionary<int, Employees> EmployeesToDictionary(Employees employees) 
{ 
    var dictionary = new Dictionary<int, Employees>(); 
    EmployeesToDictionary(employees, dictionary); 
    return dictionary; 
} 

private static void EmployeesToDictionary(Employees employees, IDictionary<int, Employees> dictionary) 
{ 
    if (employees == null) return; 
    dictionary.Add(employees.Id, employees); 
    if (employees.employees == null) return; 
    foreach (var sub in employees.employees) 
    { 
     EmployeesToDictionary(sub); 
    } 
} 

et utilisation:

var id = 5; 
var dict = EmployeesToDictionary(root); 
var employee = dict[id]; 
var manager = dict[employee.ManagerId.Value]; 

Édition: @haindl La documentation est un aveu d'échec Oui, vous avez raison. @devweb J'ai ajouté le chèque pour l'exception. Le Dictionnary est créé qu'une seule fois, vérifiez à nouveau

+0

Bienvenue dans StackOverflow! Ce serait bien si vous pouviez expliquer un peu votre code afin que nous puissions comprendre ce que vous proposez comme réponse. – haindl

+0

Semble un bon endroit pour utiliser les fonctions locales C# 7. – NetMage

+0

Dans "public static IDictionary EmployeesToDictionary (Employés employés)", vous ne pouvez pas utiliser "var dictionary = new Dictionary ();" Parce que vous créez toujours le dictionnaire à nouveau. Aussi dans le foreach si vous avez un employé sans enfants cela va vous donner une exception. – devweb

0

Si vous voulez faire une seule fois traversal, il y a cette possibilité:

public static void FindById(Employees root, int id, out Employees employees, out Employees manager) 
{ 
    employees = manager = null; 
    // todo stack 
    var stack = new Stack<Employees>(); 
    stack.Push(root); 
    // all managers seens 
    var managers = new List<Employees>(); 
    while (stack.Count > 0) 
    { 
     var e = stack.Pop(); 
     if (e.Id == id) // if found 
     { 
      employees = e; 
      manager = managers.FirstOrDefault(m => m.Id == e.ManagerId); 
      return; 
     } 
     else if (e.employees != null) 
     { 
      // add only managers with employee 
      managers.Add(e); 
      foreach (var ep in e.employees) 
      { 
       stack.Push(ep); 
      } 
     } 
    } 
}