[英]Compare two list in C# and reject or select the child list based on conditions using LINQ or foreach
我在C#中有两个相同实体的列表(一个父列表和另一个子列表可能会有所不同),它们具有很多属性,其中两个是V_ID(不是实体的唯一ID)和值。
我需要在两个列表之间进行比较,并根据条件从子列表中找出可以完全选择还是拒绝的子列表: 如果两个列表之间的V_ID相等,并且该值可以为null或等于父列表的值。
我将无法将列表转换为字典,因为如果没有实体的主要ID,我将无法唯一标识该项目。 让我知道是否可以通过字典进行操作。
请帮助我如何实现这一目标,并且我尝试了多种方式,包括LINQ,for-each等,因为子级列表中的所有实体都被完全拒绝或选中。
C#和Linq也是新手,我提供了从我的原始源代码和各种场景示例中提取的代码示例。
public class MyEntity
{
public int ID {get; set;}
public int W_ID {get; set;}
public long ValueOfW {get; set;}
public string SampleName {get; set;}
public DateTime ModifiedBy {get; set;}
//Other Properties
}
public List<long> MyMethod(List<MyEntity> parentInput, List<MyEntity> childInput)
{
var parentList = new List<MyEntity>(); //Obtained from Source A which is the parent and never changes
var childList = new List<MyEntity>(); //Obtained from Source B and converted to type MyEntity
var mySelectedIds = new List<long>();
if(parentInput.Any() && childInput.Any())
{
parentList = parentInput;
childList = childInput;
foreach(var parent in parentList)
{
foreach(var child in childList)
{
if(parent.W_ID == child.W_ID && (parent.ValueOfW == child.ValueOfW || parent.ValueOfW == 0))
{
mySelectedIds.Add(child.ID);
}
}
}
}
return mySelectedIds; //Need to do some operation after getting the IDs
}
数据样本:
父母名单
W_ID ValueOfW
----------
10 100
20 200
30 300
子清单A:
W_ID ValueOfW
----------
10 100
20 200
30 NULL
Expected Output: The child list A should be selected
as IDs are matching and the value for 30 is NULL
子清单B
W_ID ValueOfW
----------
10 100
20 200
30 301
Expected Output: The child list B should be selected
as IDs are matching and but the value for 30 is not equal
子清单C
W_ID ValueOfW
--------
10 100
20 200
30 300
40 400
Expected Output: The child list C should be selected
as IDs are matching and values match even though there is
extra item in the list.
为了简单起见,我要做的第一件事就是使比较成为其自己的功能。 这不是关键,但有助于提高可读性。 我不知道条件描述了什么,所以我将其TheCondition
。 (此外,如果条件本身存在错误,则更容易发现这种情况。)
public bool TheCondition(MyEntity parent, MyEntity child)
{
return parent.W_ID == child.W_ID
&& (parent.ValueOfW == child.ValueOfW || parent.ValueOfW == 0)
}
然后,从子列表中获取所需的元素
var selected = childList.Where(child =>
parentList.Any(parent => TheCondition(parent, child) == true));
指定== true
只是为了使其更易于阅读。 在“现实生活”中,我只会使用
var selected = childList.Where(child =>
parentList.Any(parent => TheCondition(parent, child)));
因为该函数已经返回了布尔值。
现在selected
是IEnumerable<MyEntity>
。 要获取ID列表,
var ids = selected.Select(entity => entity.ID).ToList();
我们要说的是“从子列表中选择条件,该条件适用于该孩子以及父列表中的任何父项。” 使用Any
意味着如果它确实找到了与其中一个父母的匹配,则不需要与所有其他父母进行比较。
然后,在最后一步中,我们说“从先前的实体列表中选择所有ID”,这将返回IEnumerable<int>
,然后根据这些值创建一个新的List<int>
。
如果我们再分解一些,这甚至可能更清楚一点。 我不一定每次都这样做,但是它可以使您更容易理解。 (起初我为此感到苦恼-也许您会比我快得多。)
public bool TheCondition(MyEntity parent, MyEntity child)
{
return parent.W_ID == child.W_ID
&& (parent.ValueOfW == child.ValueOfW || parent.ValueOfW == 0)
}
public bool ChildMatchesAnyParent(MyEntity child, IEnumerable<MyEntity> parents)
{
return parents.Any(parent => TheCondition(parent, child);
}
var selected = childList.Where(child => ChildMatchesAnyParent(child, parentList));
var ids = selected.Select(entity => entity.ID).ToList();
您也可以将这些链接在一起,将其列出,然后将它们组合成一个语句。
var ids = childList.Where(child => ChildMatchesAnyParent(child, parentList))
.Select(entity => entity.ID).ToList();
对我来说,我需要了解它是如何单独工作的,然后将它们组合在一起会更容易。 但是有时出于可读性考虑,将它们分开仍然是很好的。
一种可以实现此目的的方法是使用LINQ查询语言语句。
var childArray = child.ToArray(); // Convert to an array to enumerate once
return !(from e in parent // Get all the parents
from c in childArray // cross join with children
where e.W_ID == c.W_ID // filter those with only matching ID
where e.Value != c.Value && c.Value != null // filter those based on your condition
select e).Any();
请注意,布尔值NOT( !
)。 如果过滤后还有任何结果,则应拒绝该孩子。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.