2010-10-13 26 views
6

Ho una ObservableCollection, che contiene un oggetto Person. Ho una funzione di ricerca nella mia applicazione e vorrei mostrare i risultati più rilevanti in alto. Quale sarebbe il modo più efficace per farlo? Il mio attuale metodo di ricerca chiama semplicemente il metodo contains:Risultato ricerca Linq dalla corrispondenza più vicina

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

Questo funziona bene, ma i risultati sono ordinati nello stesso ordine in cui appaiono all'interno userList. Se cerco Pete, dovrebbe prima visualizzare Pete, quindi Peter quindi Peter Smith ecc. Non deve essere troppo complicato in quanto si tratta solo di un paio di migliaia (max) risultati. Il mio approccio ingenuo era di fare prima s.Name == query, visualizzare quell'elemento (se presente), quindi eseguire lo s.Name.Contains(query), rimuovere l'elemento corrispondente e aggiungerlo al risultato corrispondente precedente. Tuttavia, questo sembra un po 'dappertutto e quindi c'è un modo migliore? grazie (ps - solo il nome verrà utilizzato nella ricerca e non è possibile utilizzare i metodi SQL)

risposta

10

È possibile creare una singola routine che fornisce un nome e una stringa di query e restituisce un valore intero.

Una volta che avete, basta tornare via ordina per:

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

    return 1; 
} 

Poi fare:

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

La cosa bella di questo approccio è che, in seguito, si potrebbe estendere la routine per fornire maggiori dettagli, che ti consentono di ordinare in base a "buono" di una partita che ricevi. Ad esempio, "Pete" -> "Pietro" è probabilmente una partita migliore di "Pete" -> "Peter Smith", così si potrebbe avere la tua logica restituisce un valore diverso per le diverse opzioni ...

Se è necessario rimuovere le corrispondenze "non Pete", è possibile escludere anche una clausola Where.

+0

Grazie, ho appena testato questo e sembra funzionare perfettamente. Bello e semplice :) – Brap

7

Quello che ti serve è una sorta di funzione di punteggio per la somiglianza. Poi si può fare solo:

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

Ora non è chiaro dal vostro esempio esattamente (che è supponendo una funzione di punteggio che dà un valore compreso tra 0-100, dove il 100 è un partner perfetto.) quale dovrebbe essere la funzione di punteggio - che è per voi di risolvere :)

+0

Grazie per l'aiuto. Avrei optato per un metodo a distanza Hamming, ma potrebbe essere un po 'eccessivo e inefficiente per questo problema. – Brap

0
var results = (from s in userList 
       where s.Name.Contains(query) 
       orderBy s.Length 
       select s).ToList(); 
Problemi correlati