2009-12-13 91 views
0

也许这个问题已经被问过,但我的谷歌福和SO-搜索并没有得到我什么什么,我一直在寻找。LINQ-比较和更新值

我有一个的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只列出了“源”和“目标”

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 }; 

什么我想要做的

  1. 更新源列表,只包含山姆和安迪,因为鲍勃和托马斯不在目标列表中。我这样做

    源=(从源其中(由叔在目标选择T)p 。载(P,新PersonComparer()) 选择P).ToList();

  2. 在我“旗” SAM2和安迪真实和简被标记为默认情况下“假”的目标,我不应该改变它。

我试图用这个,但是这从目标中删除“简”

//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.Is有没有更好的方式来写查询1?

4.And最后一个简单的问题:究竟你说“=>”当你在电话

回答

2

由于桑德指出,LINQ是查询,更新不及时。

source = source.Intersect(target, new PersonComparer()).ToList(); 

说了这么多,你需要更新PersonComparer为recursive

然而,要回答的问题......你原来的

source = (from p in source where (from t in target select t) 
    .Contains(p, new PersonComparer()) select p).ToList(); 

查询会更简单地写提及。它应该是这样的:

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; 
    } 
} 
+0

>>有副作用的查询通常是一个坏主意。 明白了!谢谢。 – ram 2009-12-13 17:44:23

1

跟一个老乡编码器对于部分4 =>可以理解为goes to

+0

尼斯链接。谢谢 – ram 2009-12-13 16:56:31

+0

不用担心。我认为这是很多人想知道什么时候开始使用LINQ的问题。 – RichardOD 2009-12-13 17:05:22

1

GetHashCode()方法应该使用的obj通过实例,而不是它自己的父。

+0

好点,但比回答这个问题更多评论。更确切地说:当.Equals(a,b)返回true时,a.GetHashcode()应该等于b.GetHashCode()。另外,当.Equals返回false时,hashcodes应该有所不同 – 2009-12-13 15:40:37

+0

好吧,那么如何编写这个GetHashCode方法呢? – ram 2009-12-13 16:57:12

+0

err,可能返回obj.GetHashCode(); – recursive 2009-12-13 17:26:34

2

的LINQ并不意味着更新列表,因为它IEnumerable<T>工作。您可以根据代表您需要的集合的源和目标创建新的枚举。

像这样的东西应该工作:

var combined = source.Where(x => target.Any(y => y == x))