比较列表并获得唯一的元素

本文关键字:唯一 元素 列表 比较 | 更新日期: 2023-09-27 17:50:30

我有一个名为Parent的对象和一个名为Child的对象列表。Parent对象也有一个Child对象的列表。

public class Parent 
{
   public Parent() 
   {
      Children = new List<Child>();
   }
   public string Name { get; set; }
   public IList<Child> Children { get; set; }
}
public class Child
{
   public string Name { get; set; }
   ....
}

现在我想从列表中获取那些不存在于Parent's list of Children中的Children.

我怎么能实现这与linq/lambda表达式?

我试过的代码没有成功:

Parent parent = GetParent();
List<Child> children = GetChildren();
var notExistingChildren = children.Where(child => !parent.Children.Any(ch => ch.Name == child.Name)).ToList();

子元素有一个父元素中不存在的元素。

比较列表并获得唯一的元素

,但是这个表达式并没有得到那个元素并把它赋值给notExistingChildren。

您的方法不是很有效,因为您为children集合中的每个子枚举父子。此外,如果名称有不同的大小写,您可能会遇到问题-例如,"Bob""bob"在c#中是不同的字符串。但是,如果名称相等,您的方法应该有效:

var notExistingChildren = 
    children.Where(c => !parent.Children.Any(pc => pc.Name == c.Name))
            .ToList();

更有效和易于阅读的方式是为Child类实现EqualsGetHashCode方法(或为Child类创建自定义IEqualityComparer)。在这种情况下,您将能够使用Enumerable.Except执行设置操作:

var notExistingChildren = children.Except(parent.Children).ToList();

如果子名称可以作为它的标识,那么你可以用以下方式覆盖EqualsGetHashCode:

public override bool Equals(object obj)
{
    Child other = obj as Child;
    if (other == null)
        return false;
    return other.Name == Name;
}
public override int GetHashCode()
{
    return Name.GetHashCode();
}

顺便说一句,我用下面的样本数据尝试了你的代码,它工作得很好- Joe返回为不存在的孩子。

List<Child> children = new List<Child>
{
    new Child { Name = "Bob" },
    new Child { Name = "Joe" }
};
Parent parent = new Parent
{
    Children = new List<Child> { new Child { Name = "Bob" } }
};

如果在results中没有看到child,则parents children collection中存在同名的child。没有别的办法。

这个表达式对我来说很好。使用ch.Name.ToLower() == child.Name.ToLower()进行比较,因为您的列表可能有不同的字符大小写