2012-12-17 10 views
24

Sto provando a creare una funzione di ricerca per un progetto che restringe gli elementi in base a un input di ricerca utente e se corrisponde alle parole chiave elencate rispetto agli elementi. Per questo, sto salvando le parole chiave dell'articolo in un attributo data e facendo corrispondere la query con queste parole chiave utilizzando un modello RegExp.Espressione regolare per TUTTE le parole in una query, in qualsiasi ordine

Attualmente sto usando questa espressione, che so non è corretto e bisogno del vostro aiuto su questo:

new RegExp('\\b(' + query + ')', 'gi'))) dove query viene | valori separati della query immessa dall'utente (ad esempio \\b(meat|pasta|dinner)). Questo mi restituisce una partita, anche se c'è solo 1 partita, diciamo per esempio - meat

solo per gettare un po 'di contesto, ecco un piccolo esempio:

Se un utente digita: meat pasta dinner dovrebbe elencare tutti gli elementi che hanno TUTTE le 3 parole chiave elencate contro di esse, ad esempio meatpasta e dinner. Questi sono indipendenti dall'ordine in cui sono stati digitati.

Puoi aiutarmi con un'espressione che corrisponderà a TUTTE le parole in una query, in qualsiasi ordine?

+0

Umm, non esattamente - Devo abbinare l'intero input dell'utente con le parole chiave rispetto agli oggetti e restituire solo true se l'intero input corrisponde alle parole chiave su quegli elementi. – kayen

+0

Fondamentalmente ho bisogno di venire con un'espressione AND che AND l'utente input 'e.g. torta a base di carne e confronto con le parole chiave 'ad es. Torta semplice di kebab continentale della carne della pasta '. In questo caso, l'espressione fallirà poiché la parola chiave contiene 'carne' e' torta' ma non 'cena'. – kayen

+1

Perché non usi un semplice metodo 'stringa' per questo? Voglio dire, se non ci sono parole chiave ripetute, allora questo può essere raggiunto facilmente con Regex.Ma con parole chiave ripetute, è meglio evitare Regex qui. Basta usare la funzione 'indexOf' con un ciclo for. Oppure, potrebbe essere una funzione String migliore, di cui potrei non essere a conoscenza. –

risposta

49

È possibile raggiungere questo obiettivo sarà lookahead affermazioni

^(?=.*\bmeat\b)(?=.*\bpasta\b)(?=.*\bdinner\b).+ 

Guardalo here on Regexr

(?=.*\bmeat\b) è un positive lookahead assertion, che assicura che \bmeat\b è da qualche parte nella stringa. Lo stesso vale per le altre parole chiave e lo .+ corrisponde effettivamente all'intera stringa, ma solo se le asserzioni sono vere.

Ma corrisponderà anche su "la cena a base di carne Foobar di pasta"

4

tua regex sembra piuttosto buono:

\b(meat|pasta|dinner)\b 

Verificare che la durata delle partite è uguale al numero di parole chiave (in questo caso, tre):

string.match(re).length === numberOfKeywords 

dove re è l'espressione regolare con un g flag, numberOfKeywords è il numero di parole chiave

Questo presuppone che ci sia un re senza parole chiave ripetute.

+0

In questo modello è necessario rimuovere anche i duplicati – closure

+0

Grazie per l'aiuto! Ma sì, le parole chiave potrebbero ripetersi, quindi vado avanti con la risposta di stema sopra. +1 per la logica però. – kayen

+0

Inoltre, se hai bisogno di condizioni per gli articoli "X" di atleast dove "X" indica l'intervallo iniziale, puoi usare sotto regex (modificato per almeno un articolo) \ b (carne | pasta | cena) {1,3} \ b – vCillusion

1

Sulla base della risposta accettata Ho scritto un metodo Java semplice che costruisce l'espressione regolare da una serie di parole chiave

public static String regexIfAllKeywordsExists(String[] keywords) { 
    StringBuilder sb = new StringBuilder("^"); 

    for (String keyword : keywords) { 
     sb.append("(?=.*\\b"); 
     sb.append(keyword); 
     sb.append("\\b)"); 
    } 

    sb.append(".+"); 

    return sb.toString(); 
} 
Problemi correlati