Linq中的分层分层

时间:2010-06-23 12:40:02

标签: c# linq

如果我有一组类似于以下的员工数据:

var users = new[] 
{
   new {SupervisorId = "CEO", UserId = "CEO", UserName = "Joe"},
   new {SupervisorId = "CEO", UserId = "CIO", UserName = "Mary"},
   new {SupervisorId = "CIO", UserId = "XDIR", UserName = "Ed"},
   new {SupervisorId = "CIO", UserId = "YDIR", UserName = "Lisa"},
   new {SupervisorId = "XDIR", UserId = "AMNGR", UserName = "Steve"},
   new {SupervisorId = "AMNGR", UserId = "ASUP", UserName = "Lesley"}
};

是否可以使用Linq添加分层图层,意思是:

  • CEO = 1(上)
  • CIO = 2(第二级)
  • XDIR和YDIR = 3(第3级)
  • AMNGR = 4(等)
  • ASUP = 5(等)

我已经能够根据SupervisorId对员工进行分组,但不确定如何使“级别”发生。

var userGroups = from user in users
  group user by user.SupervisorId into userGroup
  select new
  {
    SupervisorId = userGroup.Key,
    Level = ??????
    Users = userGroup.ToList()
  };

  foreach (var group in userGroups)
  {
    Console.WriteLine("{0} - {1} - {2}", group.SupervisorId, group.Level, group.Users.Count);
  }

非常感谢。

4 个答案:

答案 0 :(得分:0)

我会在你的linq“用户对象”中添加一个排名

public class User{

  public string SupervisorId  {get;set;}
  public string UserId {get;set;}
  public string UserName   {get;set;}
  public int Level {get {  return GetRank(SupervisorId  ) ; } } 

  private int GetRank(string userId){
     if(string.IsNullOrEmpty(userId)){
         //Bad case, probably want to use a very large number
         return -1;
     }
     int level = 0;
     switch(userId){
        case "CEO":
           level  = 0;
           break;

         //insert others here

     }

  }
}

然后你的Linq你会添加一个连接。

     var userGroups = from user in users
                     join super in users on user.SupervisorId  equals super.UserId
                     group user by  user.SupervisorId into userGroup 
                     select new
    {
        SupervisorId = userGroup.Key,
        Level =  super.Level, 
        Users = userGroup.ToList()
    };

答案 1 :(得分:0)

<强>更新

这是为每个级别创建查找表的一种方法。它公平,我不知道它将如何扩展。显然,您需要调整它以从数据库中提取行。

定义一个类来保存我们的查找表

public class user{
    public string SupervisorId;
    public string UserId;   
    public int Level;
}

然后我们得到一个唯一的UserId / SupervisorId组合列表,并循环遍历列表,通过“走”树来计算每个组合的级别。

    var uniqueusers = (new user[] 
        {
            new user {SupervisorId = "CEO", UserId = "CEO"},
            new user {SupervisorId = "CEO", UserId = "CIO"},
            new user {SupervisorId = "CIO", UserId = "XDIR"},
            new user {SupervisorId = "CIO", UserId = "YDIR"},
            new user {SupervisorId = "XDIR", UserId = "AMNGR"},
            new user {SupervisorId = "AMNGR", UserId = "ASUP"}
        }).Distinct();


        foreach (var item in uniqueusers)
        {           
            int level = 0;
            user CurrentUser = item;
            while (CurrentUser.UserId != CurrentUser.SupervisorId){
                CurrentUser = uniqueusers.Where(c => c.UserId == CurrentUser.SupervisorId).FirstOrDefault();
                level++;
            } 
            item.Level = level;             
        }

现在,您可以使用uniqueusers作为查找表来确定查询的级别。例如

private int GetLevel(string userId){         
     return uniqueusers.Where(c => c.UserId == userId).FirstOrDefault().Level;    
  }

你甚至可以用一点点努力将它合并为一步。

答案 2 :(得分:0)

ILookup<string, User> subordLookup = users
  .ToLookup(u => u.SupervisorId);

foreach(User user in users)
{
  user.Subordinates = subordLookup[user.UserId].ToList();
}

User userHierarchy = user.Single(u => u.UserId == "CEO");

免责声明:

  • 不处理多位CEO。
  • 保留循环关系。
  • 留下孤儿。

答案 3 :(得分:0)

这是你在找什么?

         var levels = new[]
        {
            new { Level = 1, LevelName = "CEO" },
            new { Level = 2, LevelName = "CIO" },
            new { Level = 3, LevelName = "XDIR" },
            new { Level = 3, LevelName = "YDIR" },
            new { Level = 4, LevelName = "AMNGR" },
            new { Level = 5, LevelName = "ASUP" }
        };                        

        var userGroups = from user in users
                         join level in levels on
                         user.UserId equals level.LevelName                             
                         group new{ User = user, Level = level.Level } by new { SuperId = user.SupervisorId, Level = level.Level } into userGroup
                         select new
                            {
                                SupervisorId = userGroup.Key.SuperId,
                                Level = userGroup.Key.Level,
                                Users = userGroup.ToList()
                            };