比较列表并获得独特的元素

时间:2014-03-17 07:45:29

标签: c#

我有一个名为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; }
   ....
}

现在我希望从父母的儿童名单中不存在的列表中获取那些儿童。

我如何使用linq / lambda表达式来解决这个问题?

我试过的代码没有任何成功:

Parent parent = GetParent();
List<Child> children = GetChildren();

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

子元素有1个元素在parent.Children中不存在,但是这个表达式不会获取该元素并将其分配给notExistingChildren。

2 个答案:

答案 0 :(得分:2)

您的方法效率不高,因为您在children集合中为每个孩子列举了父母的子女。如果名称有不同的情况,你也会遇到问题 - 例如"Bob""bob"是C#中的不同字符串。但是如果名字相同,你的方法应该有效:

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

更有效且易于阅读的方法是为Equals类实施GetHashCodeChild方法(或为IEqualityComparer类创建自定义Child。在这种情况下,您将能够使用执行设置操作的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();
}

BTW我尝试使用以下示例数据编写代码并且工作正常 - 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" } }
};

如果您没有在结果中看到某个孩子,那么父母子女收藏中会存在具有相同名称的孩子。没有其他办法。

答案 1 :(得分:0)

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