LINQ检查列表<roles>是否是另一个列表<roles>的子集

时间:2015-10-20 10:09:30

标签: c# linq

我有两个Users类列表,即UsersExisting,UsersToUpdate。 类结构如下所示。

public class Users
{
    public string Name{get;set;}
    public Roles[] AvailableRoles{get;set;}
}

class Roles
{
    public int Serial{get;set;}
    public string Name{get;set;}
    public bool IsActive{get;set;}
}

我必须检查UsersToUpdate是否已经具有UsersExisting的所有角色详细信息。

EG。这是清单

UsersExisting.AvailableRoles={{1,"admin",true},{2,"hr",false},{3,"it",true}};
UsersToUpdate.AvailableRoles={{1,"admin",true},{2,"hr",false},{3,"it",true},{4,"finance",false}};

如何使用LINQ执行此操作。

我这样做。

bool isUsersUpdated = !UsersExisting.AvailableRoles
.Except(UsersToUpdate.AvailableRoles).Any();

这是抛出错误。

3 个答案:

答案 0 :(得分:2)

您可以将Serial数字与Except进行比较,这些数字似乎是角色标识符:

IEnumerable<int> existingRoles = UsersExisting
    .SelectMany(u => u.AvailableRoles.Select(r => r.Serial));
IEnumerable<int> updatingRoles = UsersToUpdate
   .SelectMany(u => u.AvailableRoles.Select(r => r.Serial));
bool isUsersUpdated = !existingRoles.Except(updatingRoles).Any();
  

我必须比较序列号和名称。

然后最好的方法是覆盖Equals中的GetHashCode + Roles或提供可以传递给IEqualityComparer<Roles>的自定义Enumerable.Except。另一种方法是使用我的代码,但选择包含序列号+名称的匿名类型:

IEnumerable<int> existingRoles = UsersExisting
    .SelectMany(u => u.AvailableRoles.Select(r => new {r.Serial,r.Name}));
IEnumerable<int> updatingRoles = UsersToUpdate
    .SelectMany(u => u.AvailableRoles.Select(r => new {r.Serial,r.Name}));
bool isUsersUpdated = !existingRoles.Except(updatingRoles).Any();

答案 1 :(得分:1)

您必须覆盖班级Equals中的方法GetHashCodeRoles才能使其发挥作用。这是因为Except使用这些方法来确定对象是否彼此相等。

在此处了解如何覆盖这些方法:

https://msdn.microsoft.com/en-US/library/ms173147(v=vs.80).aspx

答案 2 :(得分:0)

如果要比较某些自定义数据类型的对象序列,请在类中实现IEquatable泛型接口。此外,您必须覆盖Roles类中的Equals和GetHashCode方法。

我在这里创建了this dotnet小提琴。你可以看到程序的输出。

using System;
using System.Linq;
using System.Collections.Generic;

public class Program
{
    public static void Main()
    {
        Console.WriteLine("Hello World");
        var availbleRoles = new List<Roles>();
        availbleRoles.Add(new Roles() { Serial = 1, Name = "Test 1", IsActive = true });    
        availbleRoles.Add(new Roles() { Serial = 2, Name = "Test 2", IsActive = true });    
        availbleRoles.Add(new Roles() { Serial = 4, Name = "Test 4", IsActive = true });    


        var updatedRoles = new List<Roles>();
        updatedRoles.Add(new Roles() { Serial = 1, Name = "Test 1", IsActive = true }); 
        updatedRoles.Add(new Roles() { Serial = 2, Name = "Test 2", IsActive = true }); 
        updatedRoles.Add(new Roles() { Serial = 3, Name = "Test 3", IsActive = true }); 
        updatedRoles.Add(new Roles() { Serial = 4, Name = "Test 4", IsActive = true });


        var roles = updatedRoles.Except(availbleRoles);
        foreach (var role in roles)
        {
            Console.WriteLine("Serial : " + role.Serial + " Name : " + role.Name);
        }

        bool isRoleUpdated = roles.Any();

        Console.WriteLine("Role Updated : " + isRoleUpdated);
    }
}

public class Roles : System.IEquatable<Roles>
{
    public int Serial {get; set;}
    public string Name {get;set;}
    public bool IsActive {get;set;}

    public bool Equals(Roles other)
    {

        //Check whether the compared object is null.
        if (Object.ReferenceEquals(other, null)) return false;

        //Check whether the compared object references the same data.
        if (Object.ReferenceEquals(this, other)) return true;

        //Check whether the products' properties are equal.
        return Serial.Equals(other.Serial) && Name.Equals(other.Name);
    }

    // If Equals() returns true for a pair of objects 
    // then GetHashCode() must return the same value for these objects.

    public override int GetHashCode()
    {

        //Get hash code for the Name field if it is not null.
        int hashRoleName = Name == null ? 0 : Name.GetHashCode();

        // Get hash code for the Serial field.
        int hashSerial = Serial.GetHashCode();

        //Calculate the hash code for the Role.
        return hashSerial ^ hashRoleName;
    }
}

public class Users
{
    public string Name {get;set;}
    public Roles[] AvailableRoles { get; set; }
}