我有一个名为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。
答案 0 :(得分:2)
您的方法效率不高,因为您在children
集合中为每个孩子列举了父母的子女。如果名称有不同的情况,你也会遇到问题 - 例如"Bob"
和"bob"
是C#中的不同字符串。但是如果名字相同,你的方法应该有效:
var notExistingChildren =
children.Where(c => !parent.Children.Any(pc => pc.Name == c.Name))
.ToList();
更有效且易于阅读的方法是为Equals
类实施GetHashCode
和Child
方法(或为IEqualityComparer
类创建自定义Child
。在这种情况下,您将能够使用执行设置操作的Enumerable.Except
:
var notExistingChildren = children.Except(parent.Children).ToList();
如果子名称可以用作其身份,则可以通过以下方式覆盖Equals
和GetHashCode
:
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()进行比较,因为您的列表可能有不同的字符大小写