繁体   English   中英

比较C#中的两个列表,并使用LINQ或foreach根据条件拒绝或选择子列表

[英]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)));

因为该函数已经返回了布尔值。

现在selectedIEnumerable<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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM