[英]Best approach to compare if one list is subset of another in C#
I have the below two classes: 我有以下两节课:
public class FirstInner
{
public int Id { get; set; }
public string Type { get; set; }
public string RoleId { get; set; }
}
public class SecondInner
{
public int Id { get; set; }
public string Type { get; set; }
}
Again, there are lists of those types inside the below two classes: 同样,在以下两个类别中有这些类型的列表:
public class FirstOuter
{
public int Id { get; set; }
public string Name { get; set; }
public string Title { get; set; }
public List<FirstInner> Inners { get; set; }
}
public class SecondOuter
{
public int Id { get; set; }
public string Name { get; set; }
public List<SecondInner> Inners { get; set; }
}
Now, I have list of FirstOuter
and SecondOuter
. 现在,我有
FirstOuter
和SecondOuter
列表。 I need to check if FirstOuter
list is a subset of SecondOuter
list. 我需要检查,如果
FirstOuter
列表的一个子集SecondOuter
列表。
Please note: 请注意:
FirstOuter
but not in SecondOuter
. FirstOuter
中存在一些其他属性,但FirstOuter
不SecondOuter
。 When comparing subset, we can ignore their presence in SecondOuter
. SecondOuter
的存在。 FirstInner
and SecondInner
as well. FirstInner
和SecondInner
也是如此。 FirstOuterList[1]
could be found in SecondOuterList[3]
, based on Id, but inside that again need to compare that FirstOuterList[1].FirstInner[3]
, could be found in SecondOuterList[3].SecondInner[2]
, based on Id. FirstOuterList[1]
可以在找到SecondOuterList[3]
根据ID,但是这里面需要再次来比较FirstOuterList[1].FirstInner[3]
可以在发现SecondOuterList[3].SecondInner[2]
,基于ID。 I tried Intersect, but that is failing as the property names are mismatching. 我尝试了“相交”,但是由于属性名称不匹配而失败。 Another solution I have is doing the crude
for each
iteration, which I want to avoid. 我要解决的另一种解决方案是
for each
迭代都使用粗略for each
,这是我想避免的。
Should I convert the SecondOuter
list to FirstOuter
list, ignoring the additional properties? 如果我的转换
SecondOuter
列表FirstOuter
列表,忽略了附加属性?
Basically, here is a test data: 基本上,这是一个测试数据:
var firstInnerList = new List<FirstInner>();
firstInnerList.Add(new FirstInner
{
Id = 1,
Type = "xx",
RoleId = "5"
});
var secondInnerList = new List<SecondInner>();
secondInner.Add(new SecondInner
{
Id = 1,
Type = "xx"
});
var firstOuter = new FirstOuter
{
Id = 1,
Name = "John",
Title = "Cena",
Inners = firstInnerList
}
var secondOuter = new SecondOuter
{
Id = 1,
Name = "John",
Inners = secondInnerList,
}
var firstOuterList = new List<FirstOuter> { firstOuter };
var secondOuterList = new List<SecondOuter> { secondOuter };
Need to check if firstOuterList
is part of secondOuterList
(ignoring the additional properties). 需要检查是否
firstOuterList
是部分secondOuterList
(忽略额外属性)。
So the foreach
way that I have is: 所以我拥有的
foreach
方式是:
foreach (var item in firstOuterList)
{
var secondItem = secondOuterList.Find(so => so.Id == item.Id);
//if secondItem is null->throw exception
if (item.Name == secondItem.Name)
{
foreach (var firstInnerItem in item.Inners)
{
var secondInnerItem = secondItem.Inners.Find(sI => sI.Id == firstInnerItem.Id);
//if secondInnerItem is null,throw exception
if (firstInnerItem.Type != secondInnerItem.Type)
{
//throw exception
}
}
}
else
{
//throw exception
}
}
//move with normal flow
Please let me know if there is any better approach. 请让我知道是否有更好的方法。
First, do the join of firstOuterList and secondOuterList 首先,执行firstOuterList和secondOuterList的联接
bool isSubset = false;
var firstOuterList = new List<FirstOuter> { firstOuter };
var secondOuterList = new List<SecondOuter> { secondOuter };
var jointOuterList = firstOuterList.Join(
secondOuterList,
p => new { p.Id, p.Name },
m => new { m.Id, m.Name },
(p, m) => new { FOuterList = p, SOuterList = m }
);
if(jointOuterList.Count != firstOuterList.Count)
{
isSubset = false;
return;
}
foreach(var item in jointOuterList)
{
var jointInnerList = item.firstInnerList.Join(
item.firstInnerList,
p => new { p.Id, p.Type },
m => new { m.Id, m.type },
(p, m) => p.Id
);
if(jointInnerList.Count != item.firstInnerList.Count)
{
isSubset = false;
return;
}
}
Note: I am assuming Id is unique in its outer lists. 注意:我假设ID在其外部列表中是唯一的。 It means there will not be multiple entries with same id in a list.
这意味着列表中不会有多个具有相同ID的条目。 If no, then we need to use group by in above query
如果否,那么我们需要在上面的查询中使用分组
I think to break the question down.. 我想把问题分解。
If that's the case, these are a couple of working test cases: 如果是这样,这些是几个工作测试用例:
[TestMethod]
public void ICanSeeWhenInnerAndOuterCollectionsAreSubsets()
{
HashSet<int> firstInnerIds = new HashSet<int>(GetFirstOuterList().SelectMany(outer => outer.Inners.Select(inner => inner.Id)).Distinct());
HashSet<int> firstOuterIds = new HashSet<int>(GetFirstOuterList().Select(outer => outer.Id).Distinct());
HashSet<int> secondInnerIds = new HashSet<int>(GetSecondOuterList().SelectMany(outer => outer.Inners.Select(inner => inner.Id)).Distinct());
HashSet<int> secondOuterIds = new HashSet<int>(GetSecondOuterList().Select(outer => outer.Id).Distinct());
bool isInnerSubset = secondInnerIds.IsSubsetOf(firstInnerIds);
bool isOuterSubset = secondOuterIds.IsSubsetOf(firstOuterIds);
Assert.IsTrue(isInnerSubset);
Assert.IsTrue(isOuterSubset);
}
[TestMethod]
public void ICanSeeWhenInnerAndOuterCollectionsAreNotSubsets()
{
HashSet<int> firstInnerIds = new HashSet<int>(GetFirstOuterList().SelectMany(outer => outer.Inners.Select(inner => inner.Id)).Distinct());
HashSet<int> firstOuterIds = new HashSet<int>(GetFirstOuterList().Select(outer => outer.Id).Distinct());
HashSet<int> secondInnerIds = new HashSet<int>(GetSecondOuterList().SelectMany(outer => outer.Inners.Select(inner => inner.Id)).Distinct());
HashSet<int> secondOuterIds = new HashSet<int>(GetSecondOuterList().Select(outer => outer.Id).Distinct());
firstInnerIds.Clear();
firstInnerIds.Add(5);
firstOuterIds.Clear();
firstOuterIds.Add(5);
bool isInnerSubset = secondInnerIds.IsSubsetOf(firstInnerIds);
bool isOuterSubset = secondOuterIds.IsSubsetOf(firstOuterIds);
Assert.IsFalse(isInnerSubset);
Assert.IsFalse(isOuterSubset);
}
private List<FirstOuter> GetFirstOuterList() { ... }
private List<SecondOuter> GetSecondOuterList() { ... }
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.