2010-10-13 8 views
6

Mam ObservableCollection, która zawiera obiekt Person. Mam funkcję wyszukiwania w mojej aplikacji i chciałbym wyświetlić najbardziej odpowiednie wyniki na górze. Jaki byłby najskuteczniejszy sposób na zrobienie tego? Moja obecna metoda wyszukiwania po prostu wywołuje metodę contains:Wyniki wyszukiwania Linq według najbliższego dopasowania

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

Działa to dobrze, ale wyniki są zamówione w tej samej kolejności, w jakiej pojawiają się w ciągu userList. Jeśli wyszukuję numer Pete, powinien on najpierw wyświetlić Pete, następnie Peter, następnie Peter Smith itd. Nie musi być zbyt skomplikowany, ponieważ będzie miał do czynienia tylko z kilkoma tysiącami (maks.) Wyników. Moje naiwne podejście polegało najpierw na wykonaniu s.Name == query, wyświetleniu tego elementu (jeśli istnieje), a następnie wykonaniu s.Name.Contains(query), usunięciu dopasowanego przedmiotu i dołączeniu go do poprzedniego dopasowanego wyniku. Jednak wydaje się to trochę wszędzie, a więc jest lepszy sposób? dzięki (ps - w wyszukiwaniu będzie używana tylko nazwa i nie będę mógł korzystać z metod SQL)

Odpowiedz

10

Można utworzyć pojedynczą procedurę, która zawiera nazwę i ciąg zapytania, i zwraca wartość całkowitą.

Gdy trzeba, że ​​tylko powrót poprzez zamówienie przez:

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

    return 1; 
} 

następnie wykonaj:

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

Zaletą tego podejścia jest to, że później, można wydłużyć procedurę w celu zapewnienia więcej szczegółów, dzięki czemu możesz sortować według "dobrego" wyniku otrzymanego meczu. Na przykład "Pete" -> "Peter" jest prawdopodobnie lepszym rozwiązaniem niż "Pete" -> "Peter Smith", więc możesz mieć swoją logikę zwracającą inną wartość dla różnych opcji ...

Jeśli trzeba usunąć "non-Pete" mecze, można również wykluczyć z klauzulą ​​Where, jak również.

+0

Dzięki, właśnie to przetestowałem i wygląda na to, że działa idealnie. Miło i prosto :) – Brap

7

Potrzebna jest funkcja oceny podobieństwa. Następnie można po prostu zrobić:

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

Teraz to nie wynika z twojej przykład dokładnie (to przy założeniu, funkcję punktacji, która daje wartość z przedziału 0-100, gdzie 100 to idealne dopasowanie.) jaka powinna być funkcja oceniania - to do ciebie zadziałać :)

+0

Dzięki za pomoc. Miałem zamiar zastosować metodę odległości Hamminga, ale może to być trochę przesada i nieskuteczne dla tego problemu. – Brap

0
var results = (from s in userList 
       where s.Name.Contains(query) 
       orderBy s.Length 
       select s).ToList(); 
Powiązane problemy