linq – 从n个列表中返回常用项

我正在为我们的Intranet应用程序编写一个简单的搜索页面。 当用户搜索n个单词时,我创建n个命中列表,然后只想返回所有列表共有的结果。

我有一些工作使用List因此:

 var list1 = new List {1,2,3,4,5,8,10}; var list2 = new List {3,5,6,9,10,11}; var list3 = new List {3,4,5,10}; var listOfLists = new List<List>{list1,list2,list3}; var results = listOfLists.Aggregate((prevList, nextList) => prevList .Intersect(nextList) .ToList()); results.Dump(); //correctly returns 3,5,10, which are common to all lists 

但是,如果我在我的SearchResults类中尝试此操作,则无法获得任何结果。 这是代码:

 //results from first search word "howard" List list1 = new List(); list1.Add(new SearchResult ("a.html","howard kent")); list1.Add(new SearchResult ("b.html","howard shaw")); //the common item list1.Add(new SearchResult ("c.html","howard smith")); list1.Add(new SearchResult ("d.html","howard moore")); //results from second search word "shaw" List list2 = new List(); list2.Add(new SearchResult ("e.html","jon shaw")); list2.Add(new SearchResult ("b.html","howard shaw")); //the common item list2.Add(new SearchResult ("f.html","chris shaw")); //could be n further lists... //make a list of lists List<List> searchLists = new List<List>(); searchLists.Add(list1); searchLists.Add(list2); //find results that are common to all lists. //Doesn't work - returns nil items, should return 1 var results = searchLists .Aggregate((prevList, nextList) => prevList .Intersect(nextList) .ToList()); results.Dump(); } class SearchResult { public string Url{get;set;} public string SearchText { get; set; } //constructor public SearchResult(string url,string searchText) { Url = url; SearchText = searchText; } 

我该如何更改查询以返回我想要的结果?

这是因为SearchResult对象不是相同的对象,尽管它们具有相同的数据。 您可以通过实现IEquatable接口来解决此问题。 http://msdn.microsoft.com/en-us/library/ms131187(v=vs.110).aspx

IE浏览器。

 public class SearchResult : IEquatable { public string Url{get;set;} public string SearchText { get; set; } public bool Equals(SearchResult other) { if (other == null) return false; return string.Concat(this.Url, this.SearchText).Equals(string.Concat(other.Url, other.SearchText), StringComparison.OrdinalIgnoreCase); } } 

另一种解决方案是实现IEqualityComparer并将其传递给Enumerable.Intersect方法。

您可以使用Enumberable.Intersect来获取常用项。 但在你的情况下,你正在比较两个对象。 因此,您需要实现IEqualityComparer接口并创建自己的比较器类。

我假设你的SearchResult类是这样的

 public class SearchResult { public SearchResult(string first, string second) { First = first; Second = second; } public string First { get; set; } public string Second { get; set; } } 

现在IEqualityComparer接口实现。

  public class MyCompare : IEqualityComparer { public bool Equals(SearchResult x, SearchResult y) { return (x.First == y.First) && ((x.Second == y.Second)); } public int GetHashCode(SearchResult obj) { unchecked { int hash = 17; hash = hash * 23 + obj.First.GetHashCode(); hash = hash * 23 + obj.Second.GetHashCode(); return hash; } } } 

重要的一点是在GetHashCode ,我们需要将两个属性合并而不是一个。 如果我们比较单一属性那么它会很简单

 return obj.A.GetHashCode(); 

但是我们在这里比较多个属性。所以我们需要改变它的实现。 感谢@Tim到他们的post

现在,您可以使用Intersect方法获取此类常用项

 var common = list1.Intersect(list2,new MyCompare()).ToList();