在集合之间查找唯一对象
Finding Unique Objects between collections
我有一个测试,我创建了两个列表。一个代表我已经从一个来源(我无法控制)收集的数据,另一个代表我的存储库中已有的已知数据。
它们看起来像这样:
var newAccounts = new[]
{
new Account
{
Id = 1,
SA_ID = 1,
SA_Name = "Sa_Name1",
RelationshipType = "new",
LE_ID = 1,
LE_GroupID = 1,
SiteID = 1,
MinDate = DateTime.Now.AddDays(-1),
MaxDate = DateTime.Now.AddDays(1),
DaysOn = 1,
Child1 = new List<Child1>{ new Child1
{
SiteID = 1,
MaxDate = DateTime.Today.AddDays(7),
MinDate = DateTime.Today.AddDays(1),
}
},
Child2 = new List<Child2>
{
new Child2
{
SA_ID = 1,
LastUpdate = DateTime.Now.AddDays(-1),
CommentText = "Account added",
Status = AccountStatus.AccountAdded.ToString(),
}
}
},
new Account
{
Id = 2,
SA_ID = 2,
SA_Name = "Sa_Name2",
RelationshipType = "new",
LE_ID = 2,
LE_GroupID = 2,
SiteID = 2,
MinDate = DateTime.Now.AddDays(-2),
MaxDate = DateTime.Now.AddDays(2),
DaysOn = 2,
},
new Account
{
Id = 3,
SA_ID = 3,
SA_Name = "Sa_Name3",
RelationshipType = "new",
LE_ID = 3,
LE_GroupID = 3,
SiteID = 3,
MinDate = DateTime.Now.AddDays(-3),
MaxDate = DateTime.Now.AddDays(3),
DaysOn = 3,
}
};
var knownAccounts = new[]
{
new Account
{
Id = 1,
SA_ID = 1,
SA_Name = "Sa_Name1",
RelationshipType = "new",
LE_ID = 1,
LE_GroupID = 1,
SiteID = 1,
MinDate = DateTime.Now.AddDays(-1),
MaxDate = DateTime.Now.AddDays(1),
DaysOn = 1,
Child1 = new List<Child1>{ new Child1
{
SiteID = 1,
MaxDate = DateTime.Today.AddDays(7),
MinDate = DateTime.Today.AddDays(1),
}
},
Child2 = new List<Child2>
{
new Child2
{
SA_ID = 1,
LastUpdate = DateTime.Now.AddDays(-1),
CommentText = "Account added",
Status = AccountStatus.AccountAdded.ToString(),
}
}
}
};
在我的单元测试中,我想从 newAccounts
中删除 Account ID 1
,所以我的集合中只剩下 2 个条目。这些是我迄今为止的尝试:
public List<T> ReturnUniqueEntriesList<T>(List<T> newAccounts, List<T> knownAccounts)
{
var a = knownAccounts.Intersect(newAccounts).ToList();
var listA = newAccounts.Except(knownAccounts).ToList();
var listB = knownAccounts.Except(newAccounts).ToList();
var result = listB.Intersect(listA).ToList();
return result;
}
当我运行这个最终结果是0。a
也returns 0和listA
&listB
只是return他们各自的对象。
我在这里做错了什么/遗漏了什么?任何帮助将不胜感激
重写 Account 的 Equals 和 GetHashcode,使它们不依赖于默认实现(对象的内存地址)。这意味着 C# 将能够在执行 Except 时正确地将它们等同起来。
例如:
public class Account{
public override bool Equals(object other){
return other is Account a && a.Id == this.Id; //nb; is returns false if other is a null, even if it is an Account
}
public override int GetHashCode(){
return Id.GetHashCode();
}
}
实际上,以下两个帐户非常不同:
var a = new Account { Id = 1 };
var b = new Account { Id = 1 };
..因为它们位于不同的内存地址。
通过覆盖 Equals 以便它比较另一个的 Id,而不管其他属性,您就可以从本质上实现您似乎描述的“具有相同 ID 的两个帐户对象是等效的”的情况
如果其他属性因素影响决策,也添加它们。 Hashcode.Combine 是一种有用的方法,可以组合多个哈希码来解决获取多个属性的哈希码以生成合适的新信号哈希码的难题 - https://docs.microsoft.com/en-us/dotnet/api/system.hashcode.combine?view=net-5.0
我有一个测试,我创建了两个列表。一个代表我已经从一个来源(我无法控制)收集的数据,另一个代表我的存储库中已有的已知数据。
它们看起来像这样:
var newAccounts = new[]
{
new Account
{
Id = 1,
SA_ID = 1,
SA_Name = "Sa_Name1",
RelationshipType = "new",
LE_ID = 1,
LE_GroupID = 1,
SiteID = 1,
MinDate = DateTime.Now.AddDays(-1),
MaxDate = DateTime.Now.AddDays(1),
DaysOn = 1,
Child1 = new List<Child1>{ new Child1
{
SiteID = 1,
MaxDate = DateTime.Today.AddDays(7),
MinDate = DateTime.Today.AddDays(1),
}
},
Child2 = new List<Child2>
{
new Child2
{
SA_ID = 1,
LastUpdate = DateTime.Now.AddDays(-1),
CommentText = "Account added",
Status = AccountStatus.AccountAdded.ToString(),
}
}
},
new Account
{
Id = 2,
SA_ID = 2,
SA_Name = "Sa_Name2",
RelationshipType = "new",
LE_ID = 2,
LE_GroupID = 2,
SiteID = 2,
MinDate = DateTime.Now.AddDays(-2),
MaxDate = DateTime.Now.AddDays(2),
DaysOn = 2,
},
new Account
{
Id = 3,
SA_ID = 3,
SA_Name = "Sa_Name3",
RelationshipType = "new",
LE_ID = 3,
LE_GroupID = 3,
SiteID = 3,
MinDate = DateTime.Now.AddDays(-3),
MaxDate = DateTime.Now.AddDays(3),
DaysOn = 3,
}
};
var knownAccounts = new[]
{
new Account
{
Id = 1,
SA_ID = 1,
SA_Name = "Sa_Name1",
RelationshipType = "new",
LE_ID = 1,
LE_GroupID = 1,
SiteID = 1,
MinDate = DateTime.Now.AddDays(-1),
MaxDate = DateTime.Now.AddDays(1),
DaysOn = 1,
Child1 = new List<Child1>{ new Child1
{
SiteID = 1,
MaxDate = DateTime.Today.AddDays(7),
MinDate = DateTime.Today.AddDays(1),
}
},
Child2 = new List<Child2>
{
new Child2
{
SA_ID = 1,
LastUpdate = DateTime.Now.AddDays(-1),
CommentText = "Account added",
Status = AccountStatus.AccountAdded.ToString(),
}
}
}
};
在我的单元测试中,我想从 newAccounts
中删除 Account ID 1
,所以我的集合中只剩下 2 个条目。这些是我迄今为止的尝试:
public List<T> ReturnUniqueEntriesList<T>(List<T> newAccounts, List<T> knownAccounts)
{
var a = knownAccounts.Intersect(newAccounts).ToList();
var listA = newAccounts.Except(knownAccounts).ToList();
var listB = knownAccounts.Except(newAccounts).ToList();
var result = listB.Intersect(listA).ToList();
return result;
}
当我运行这个最终结果是0。a
也returns 0和listA
&listB
只是return他们各自的对象。
我在这里做错了什么/遗漏了什么?任何帮助将不胜感激
重写 Account 的 Equals 和 GetHashcode,使它们不依赖于默认实现(对象的内存地址)。这意味着 C# 将能够在执行 Except 时正确地将它们等同起来。
例如:
public class Account{
public override bool Equals(object other){
return other is Account a && a.Id == this.Id; //nb; is returns false if other is a null, even if it is an Account
}
public override int GetHashCode(){
return Id.GetHashCode();
}
}
实际上,以下两个帐户非常不同:
var a = new Account { Id = 1 };
var b = new Account { Id = 1 };
..因为它们位于不同的内存地址。
通过覆盖 Equals 以便它比较另一个的 Id,而不管其他属性,您就可以从本质上实现您似乎描述的“具有相同 ID 的两个帐户对象是等效的”的情况
如果其他属性因素影响决策,也添加它们。 Hashcode.Combine 是一种有用的方法,可以组合多个哈希码来解决获取多个属性的哈希码以生成合适的新信号哈希码的难题 - https://docs.microsoft.com/en-us/dotnet/api/system.hashcode.combine?view=net-5.0