可能这个问题之前已经被问过了,但是我的google-fu和SO-Search并没有让我得到我想要的东西。
我有一个自定义类,以及一个用IEqualityComparer实现的自定义类比较器(用于检查类的相等性)。
public class Person
{
public string Name { get; set; }
public bool Flag { get; set; }
}
public class PersonComparer : IEqualityComparer<Person>
{
#region IEqualityComparer<Person> Members
public bool Equals(Person x, Person y)
{
//case insensitive compare
return string.Equals(x.Name, y.Name, StringComparison.OrdinalIgnoreCase);
}
public int GetHashCode(Person obj)
{
return base.GetHashCode();
}
#endregion
}
在代码的主要部分我有2个列表“source”和“target”
Person bob = new Person() { Name = "Bob" };
Person sam = new Person() { Name = "Sam" };
Person andy = new Person() { Name = "Andy" };
Person thomas = new Person() { Name = "Thomas" };
Person jimmy = new Person() { Name = "Jimmy" };
Person sam2 = new Person() { Name = "sam" }; // note the lower case
Person jane = new Person() { Name = "Jane" };
List<Person> source = new List<Person>() { bob, sam, andy, thomas };
List<Person> target = new List<Person>() { sam2, andy,jane };
我想做什么
更新源列表仅包含sam和andy,因为bob和thomas不在目标列表中。我这样做了
source =(来自p in source where(from t in target select t) .Contains(p,new PersonComparer()) 选择p).ToList();
在目标中我应该“标记”sam2并且andy为true而jane默认标记为“false”,我不应该更改它。
我尝试过使用它,但这会从目标
中删除“jane”//sets sam2 & andy to true, removes Jane
target = (from p in target.Select(t => { t.Flag = true; return t; })
where (from s in source
select s).Intersect(select p).ToList();
任何LINQ大师能否告诉我我做错了什么?
3.有更好的方法来编写查询1吗?
4.最后一个小问题:你怎么说“=&gt;”当你通过电话与同事谈话时
答案 0 :(得分:2)
Linq并不打算更新列表,因为它在IEnumerable<T>
上运行。您可以根据表示所需集合的源和目标创建新的可枚举。
这样的事情应该有效:
var combined = source.Where(x => target.Any(y => y == x))
答案 1 :(得分:2)
正如桑德指出的那样,LINQ用于查询,而不是更新。
然而,回答问题......
的原始查询source = (from p in source where (from t in target select t)
.Contains(p, new PersonComparer()) select p).ToList();
更简单地写成:
source = source.Intersect(target, new PersonComparer()).ToList();
话虽如此,您需要将PersonComparer更新为recursive
。它应该是这样的:
public int GetHashCode(Person obj)
{
return obj == null ? 0
: StringComparer.OrdinalIgnoreCase.GetHashCode(obj.Name);
}
我恐怕我不太了解你的第二个查询...但如果你想改变现有的对象,我建议使用foreach
循环而不是尝试使用LINQ。有副作用的查询通常是个坏主意。
你可能意思是:
// You may want to make some singleton instance available, as this has no state
PersonComparer comparer = new PersonComparer();
foreach (Person person in target)
{
if (source.Contains(person, comparer))
{
person.Flag = true;
}
}
答案 2 :(得分:1)
对于第4部分。=&gt;可以理解为goes to。
答案 3 :(得分:1)
GetHashCode()
方法应该使用obj
传递的实例,而不是它自己的父实例。