我正在为我们的Intranet应用程序编写一个简单的搜索页面。当用户搜索n个单词时,我创建了n个命中列表,然后只想返回所有列表共有的结果。
我有一些使用List<int>
的工作因此:
var list1 = new List<int> {1,2,3,4,5,8,10};
var list2 = new List<int> {3,5,6,9,10,11};
var list3 = new List<int> {3,4,5,10};
var listOfLists = new List<List<int>>{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<SearchResult> list1 = new List<SearchResult>();
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<SearchResult> list2 = new List<SearchResult>();
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<SearchResult>> searchLists = new List<List<SearchResult>>();
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;
}
如何更改查询以返回我想要的结果?
答案 0 :(得分:3)
这是因为SearchResult
个对象不是相同的对象,尽管它们具有相同的数据。您可以通过实现IEquatable<T>
接口来解决此问题。 http://msdn.microsoft.com/en-us/library/ms131187(v=vs.110).aspx
即
public class SearchResult : IEquatable<SearchResult>
{
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<T>
并将其传递给Enumerable.Intersect方法。
答案 1 :(得分:1)
您可以使用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<SearchResult>
{
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<SearchResult>(list2,new MyCompare()).ToList();