我在 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 ( !
)。如果过滤后有任何结果,则应拒绝该子项。