Результаты поиска Linq по ближайшему совпадению - PullRequest
6 голосов
/ 13 октября 2010

У меня есть ObservableCollection, которая содержит Person объект.У меня есть функция поиска в моем приложении, и я хотел бы отображать наиболее релевантные результаты в верхней части.Что было бы наиболее эффективным способом сделать это?Мой текущий метод поиска просто вызывает метод contains:

 var results = (from s in userList
               where s.Name.Contains(query)
               select s).ToList();

Это отлично работает, но результаты упорядочены в том же порядке, в котором они появляются в userList.Если я ищу Pete, то сначала должно отображаться Pete, затем Peter, затем Peter Smith и т. Д. Это не должно быть слишком сложным, так как будет иметь дело только с парой тысяч (максимум)Результаты.Мой наивный подход состоял в том, чтобы сначала выполнить s.Name == query, отобразить этот элемент (если есть), затем выполнить s.Name.Contains(query), удалить сопоставленный элемент и добавить его к предыдущему сопоставленному результату.Тем не менее, это кажется немного повсеместно, и есть ли лучший способ?спасибо (ps - при поиске будет использоваться только имя, а я не могу использовать методы SQL)

Ответы [ 3 ]

10 голосов
/ 13 октября 2010

Вы можете создать одну подпрограмму, которая предоставляет имя и строку запроса и возвращает целочисленное значение.

Получив это, просто верните по порядку:

int QueryOrder(string query, string name)
{
     if (name == query)
         return -1;
     if (name.Contains(query))
         return 0;

     return 1; 
}

Затем выполните:

var results = userList.OrderBy(s => QueryOrder(query, s.Name));

Хорошая вещь в этом подходе заключается в том, что позже вы можете расширить процедуру, чтобы предоставить больше деталей, что позволит вам отсортировать, насколько «хорошо» совпадение вы получите.Например, «Пит» -> «Питер», вероятно, лучше подходит, чем «Пит» -> «Питер Смит», поэтому вы могли бы заставить свою логику возвращать другое значение для различных опций ...

Если вам нужно удалить совпадения «не по Питу», вы также можете исключить их с помощью предложения Where.

7 голосов
/ 13 октября 2010

То, что вам нужно, это какая-то функция оценки за сходство. Тогда вы можете просто сделать:

from s in userList
let score = Score(s, query)
where score > 80
orderby score descending
select s;

(Предполагается, что функция подсчета очков дает значение от 0 до 100, где 100 - идеальное совпадение.)

Теперь из вашего примера неясно точно какой должна быть функция подсчета очков - это вам нужно решить:)

0 голосов
/ 24 февраля 2017
var results = (from s in userList
               where s.Name.Contains(query)
               orderBy s.Length
               select s).ToList();
...