Custom Comparer против сбоя параметра
Я пытаюсь написать собственный компаратор, чтобы отсортировать список результатов поиска на основе сходства. Я хотел бы, чтобы термин, наиболее похожий на введенный поисковый термин, сначала отображался в списке, за которым следовали фразы, начинающиеся с поисковой фразы, а затем все остальные значения в алфавитном порядке.
Учитывая этот тестовый код:
string searchTerm = "fleas";
List<string> list = new List<string>
{
"cat fleas",
"dog fleas",
"advantage fleas",
"my cat has fleas",
"fleas",
"fleas on my cat"
};
Я пытаюсь использовать этот Comparer:
public class MatchComparer : IComparer<string>
{
private readonly string _searchTerm;
public MatchComparer(string searchTerm)
{
_searchTerm = searchTerm;
}
public int Compare(string x, string y)
{
if (x.Equals(_searchTerm) ||
y.Equals(_searchTerm))
return 0;
if (x.StartsWith(_searchTerm) ||
y.StartsWith(_searchTerm))
return 0;
if (x.Contains(_searchTerm))
return 1;
if (y.Contains(_searchTerm))
return 1;
return x.CompareTo(y);
}
Вызов list.Sort(новый MatchComparer(searchTerm) приводит к тому, что "у моей кошки есть блохи" в верхней части списка.
Я думаю, что я должен делать что-то странное / странное здесь.. Что-то здесь не так или есть лучший подход к тому, что я пытаюсь сделать?
Спасибо!
1 ответ
Вы не используете все возможные возвращаемые значения для CompareTo
-1 == x сначала 0 == равны 1 == y сначала
Вы хотите что-то более подобное
public class MatchComparer : IComparer<string>
{
private readonly string _searchTerm;
public MatchComparer(string searchTerm)
{
_searchTerm = searchTerm;
}
public int Compare(string x, string y)
{
if (x.Equals(y)) return 0; // Both entries are equal;
if (x.Equals(_searchTerm)) return -1; // first string is search term so must come first
if (y.Equals(_searchTerm)) return 1; // second string is search term so must come first
if (x.StartsWith(_searchTerm)) {
// first string starts with search term
// if second string also starts with search term sort alphabetically else first string first
return (y.StartsWith(_searchTerm)) ? x.CompareTo(y) : -1;
};
if (y.StartsWith(_searchTerm)) return 1; // second string starts with search term so comes first
if (x.Contains(_searchTerm)) {
// first string contains search term
// if second string also contains the search term sort alphabetically else first string first
return (y.Contains(_searchTerm)) ? x.CompareTo(y) : -1;
}
if (y.Contains(_searchTerm)) return 1; // second string contains search term so comes first
return x.CompareTo(y); // fall back on alphabetic
}
}