LINQ检查列表是否< role >是另一个列表<角色>的子集
本文关键字:列表 角色 子集 另一个 role 检查 是否 LINQ | 更新日期: 2023-09-27 18:18:39
我有两个列表的用户类即UsersExisting, userstouupdate。类结构如下:
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的所有角色详细信息。
。这是列表
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();
您可以比较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();
我必须比较序列号和名称。
,那么最好的方法是覆盖Roles
中的Equals
+ GetHashCode
,或者提供一个可以传递给Enumerable.Except
的自定义IEqualityComparer<Roles>
。另一种方法是使用我的代码,但选择一个包含串行+名称的匿名类型:
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();
您必须在类Roles
中重写Equals
和GetHashCode
方法才能使此工作。这是因为Except
使用这些方法来确定对象是否彼此相等。
查看如何重写这些方法:
https://msdn.microsoft.com/en-US/library/ms173147 (v = vs.80) . aspx
如果您想比较某些自定义数据类型的对象序列,请在类中实现IEquatable泛型接口。另外,你必须重写Roles类中的Equals和GetHashCode方法。
我在这里创建了这个。net提琴。您可以看到程序的输出。
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; }
}