【问题标题】:How to build this LINQ expression?如何构建这个 LINQ 表达式?
【发布时间】:2012-11-07 18:17:38
【问题描述】:

我有一个看起来像这样的类:

class UserProfile { public int Id; public int? ParentId; public string Name; public string Role; }

每个 UserProfile 都是用户或管理员。每个用户可能是单个管理员的孩子,其 Id 存储在用户的 ParentId 中。下面是一个例子:

IEnumerable<UserProfile> users = new List<UserProfile>{
        new UserProfile(){Id = 1, ParentId = null,  Name = "Admin1", Role = "Admin" },
        new UserProfile(){Id = 2, ParentId = 1,  Name = "User2", Role = "Admin" },
        new UserProfile(){Id = 3, ParentId = 1,  Name = "User3", Role = "Admin" },
        new UserProfile(){Id = 3, ParentId = null,  Name = "Admin2", Role = "Admin" },
        new UserProfile(){Id = 4, ParentId = 3,  Name = "User4", Role = "Admin" },
        new UserProfile(){Id = 5, ParentId = null,  Name = "User5", Role = "Admin" },
        new UserProfile(){Id = 6, ParentId = 3,  Name = "User6", Role = "Admin" },
    };  

我需要重新排列此列表或创建另一个列表,以便按特定顺序排列: 所有管理员及其用户:

  • 管理员1(详细信息)
  • 用户 2(详细信息)
  • User3(详细信息)
  • User5(详细信息)
  • Admin2(详细信息)
  • 用户 4(完整详细信息)
  • User6(详细信息)

我尝试先将它们分开,但我不知道如何按所需的顺序合并它们。

var adminsOnly = users.Where(p => p.Role.Equals("Admin")).OrderBy(p => p.Id);
var usersOnly = users.Where(p => p.Role.Equals("User")).OrderBy(p => p.Id);

非常感谢。

注意:可以有没有管理员的用户,也可以有没有用户的管理员。

【问题讨论】:

  • 所以您只想将它​​们排序在一个列表中,以便顺序为:A1、U2、U3、U5、A2、U4、U6?
  • 是的,最后我需要按特定顺序获取相同类型的 IEnumerable 列表。

标签: c# linq collections lambda


【解决方案1】:
var users = users.OrderBy(p => p.ParentId ?? p.Id).ThenBy(p => p.Role);

【讨论】:

    【解决方案2】:

    试试这个:

    users.Where(x => x.Role == "User" && x.ParentID == null)
         .Concat(users.Where(x => x.Role == "Admin")
                      .ToDictionary(x => x, 
                                    x => users.Where(u => u.ParentId == x.Id));
                      .SelectMany(x => new[] {x.Key}.Concat(x.Value)));
    

    这将为您提供IEnumerable&lt;UserProfile&gt;,所有用户都列在其管理员之后,所有没有管理员的用户列在最前面。

    【讨论】:

    • 好主意,但我需要获取一维列表,如原始列表:IEnumerable
    • @Sigourney_Weaver - 您希望在哪里对没有管理员的用户进行排序?在第一个管理员之前?还是贴在最后,让它们看起来像是属于最后一个管理员?
    • @Sigourney_Weaver - 假设您希望将它们列在第一个管理员之前(这是我放置它们的位置),请尝试我的更新代码。如果您希望它们最后列出,只需交换外部 .Where().Concat() 的顺序
    【解决方案3】:

    鉴于问题中的新信息,伊斯特恩的回答似乎是最好的。我看到的唯一缺点是没有管理员的用户将按他们的ID排序到列表中,不一定在开头或结尾。

    【讨论】:

    • 在此代码中,Admin 和 user 将绑定在 (ParentId ?? Id) 中,您只需添加第二个排序即可打破联系(我使用了角色)。
    • @Istern:我不这么认为,因为用户的 ID 在最后添加到排序分数中。只要没有用户溢出(这里是 1000),就不会有平局。
    • 重点是 1000 仅用于添加 ID 以打破平局。如果 (Parent ?? Id) 部分绑定了 Admin 和他的用户,您只需要使用辅助排序来解绑。
    • UserId 和 ParentId 一样都是数字字符串。我只是提供了一个简化版本,UserID 或 ParentID 可以是“A001B2354566”之类的东西。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-07-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-03-21
    相关资源
    最近更新 更多