PDA

View Full Version : [JAVA]Ricerca sottostringa con n parole antecedenti e successive


Slashmc
10-03-2011, 00:14
Ciao a tutti, vi espongo brevemente il mio problema: ho la necessita' di trovare, all'interno di una Stringa contenente un testo, una determinata parola e di far visualizzare le N parole precedenti e le N parole successive alla parola cercata.
Ho pensato di risolvere questo problema con una regex ma probabilmente sbaglio qualcosa...
Vi riporto qui di seguito il mio codice spiegandovi la mia idea:

Ho creato una funzione che presa la parola da cercare e il numero di parole antecedenti e successive da far visualizzare crea la regex:
/**
* Crea la regex per la ricerca della parola all'interno della Stringa
* @param s: parola da ricercare nella Stringa
* @param n: Numero di parole antecedenti e successive alla parola data
* @return Regex per la ricerca
*/
public String createRegex(String s, int n){
String res = new String();
String before = new String("[a-zA-Z0-9'!\"()-_]+[\\s+|!|\"|'|(|)]+");
String after = new String("[\\s+|!|\"|'|(|)]+[a-zA-Z0-9'!\"()-_]+");
for(int i=0; i<n;i++){
res+=before;
}
res+=s;
for(int i=0; i<n;i++){
res+=after;
}
System.out.println("Regex: "+res);
return res;
}

Un esempio di regex prodotta da questa funzione (con s=occhi e n=2) sarebbe:
[a-zA-Z0-9'!"()-_]+[\s+|!|"|'|(|)]?+[a-zA-Z0-9'!"()-_]+[\s+|!|"|'|(|)]+occhi[\s+|!|"|'|(|)]?+[a-zA-Z0-9'!"()-_]+[\s+|!|"|'|(|)]+[a-zA-Z0-9'!"()-_]+

Questa funzione viene appunto richiamata prima di effettuare la find nella stringa:
String regex = createRegex(word, nWord);
Pattern pattern = Pattern.compile(regex);
Matcher matcher = pattern.matcher(res);
while(matcher.find()){
String foundedWord =matcher.group();
output.add(foundedWord);
}
dove res e' la Stringa in cui effettuare la richiesta e output e' un Vector di String cosi' definito: Vector<String> output = new Vector<String>();

Purtroppo questo mio approccio va incontro a numerosi problemi in quanto ho riscontrato dei casi in cui la ricerca della parola non va a buon fine.
Ad esempio se la Stringa fosse: "Codifica automaticamente i link nel testo", la parola da ricercare fosse "automaticamente" e il numero di parole precedenti e successive da far visualizzare fosse "4", la regex non ritorna nessuna corrispondenza in quanto non riesce a prendere le 4 parole precedenti a automaticamente (in quanto ve ne sono solo due)....

Potreste suggerirmi una regex corretta per effettuare questa operazione e potreste indicarmi cortesemente l'errore presente nella regex da me sviluppata?

Spero di essere stato abbastanza chiaro...Grazie per l'eventuale aiuto!

Slashmc
11-03-2011, 11:47
Nessuno e' in grado di darmi una mano?

banryu79
11-03-2011, 11:52
Nessuno e' in grado di darmi una mano?
E' proprio neccessario/conveniente usare le regex per risolvere questo problema?

Slashmc
11-03-2011, 12:02
E' proprio neccessario/conveniente usare le regex per risolvere questo problema?

Ciao grazie per la risposta!
No non ho vincoli a riguardo...pensavo potesse essere l'approccio migliore per risolvere questo tipo di problema...ma ad essere sincero non ho mai usato le espressioni regolari in precedenza e quindi magari ho una visione errata del loro utilizzo...tu come risolveresti questo problema?

banryu79
11-03-2011, 12:23
Ciao grazie per la risposta!
No non ho vincoli a riguardo...pensavo potesse essere l'approccio migliore per risolvere questo tipo di problema...ma ad essere sincero non ho mai usato le espressioni regolari in precedenza e quindi magari ho una visione errata del loro utilizzo...tu come risolveresti questo problema?
Umm... per prima cosa cercherei di analizzare bene il problema per prevedere eventuali casi limite e scegliere come gestirli prima di cominciare a scrivere del codice. Ad esempio, posto che tutto quello che sappiamo del problema è riassunto così:

...ho la necessita' di trovare, all'interno di una Stringa contenente un testo, una determinata parola e di far visualizzare le N parole precedenti e le N parole successive alla parola cercata.

e posto che sappiamo come spezzare una stringa di testo nelle singole parole che la compongono (1° sottoproblema da risolvere; io al momento opterei per il metodo split di String) come deve essere gestito questo caso?
parola target = pappa
testo in input = "Voglio subito tutta la mia pappa pappa pappa prima che inizi il film!"

Slashmc
11-03-2011, 13:44
... posto che sappiamo come spezzare una stringa di testo nelle singole parole che la compongono (1° sottoproblema da risolvere; io al momento opterei per il metodo split di String) come deve essere gestito questo caso?
parola target = pappa
testo in input = "Voglio subito tutta la mia pappa pappa pappa prima che inizi il film!"

Ipotizzando che il numero di parole antecedenti e successive da far visualizzare sia 2 (N=2) nel caso da te indicato si dovrebbero avere in output le 3 seguenti sottostringhe:
1) la mia PAPPA pappa pappa
2) mia pappa PAPPA pappa prima
3) pappa pappa PAPPA prima che

C'e' pero' da considerare che io devo trovare nel testo solo la parola PAPPA e non parole che contengano la parola PAPPA (come ad esempio "pappagallo")...indendo dire che in questo caso:
parola target = pappa
numero parole pre/post = 2
testo in input = "Voglio subito tutta la mia pappa pappa pappagallo prima che inizi il film!"
l'output dovrebbe essere (al contrario di prima):
1) la mia PAPPA pappa pappagallo
2) mia pappa PAPPA pappagallo prima

per fare cio' all'interno con il metodo split di String credo che si dovrebbe usare comunque una regex...o sbaglio?

banryu79
11-03-2011, 13:52
Ipotizzando che...
[snip]
per fare cio' all'interno con il metodo split di String credo che si dovrebbe usare comunque una regex...o sbaglio?
Avrei usato split per ottenere un array di String i cui singoli elementi sono le parole contenute nel testo da analizzare.
Avendo quello in mano si tratta poi di fare una banale ricerca nell'array utilizzando gli indici.

Don[ITA]
11-03-2011, 14:09
Si può risolvere comodamente con split(" ") ed una normale ricerca lineare della parola che ti interessa, come suggerito dal saggio banryu :D
Ma se:

input = "a b c"
n = 1
target = "a"

quale dev'essere l'output???

Slashmc
11-03-2011, 15:26
;34662326']Si può risolvere comodamente con split(" ") ed una normale ricerca lineare della parola che ti interessa, come suggerito dal saggio banryu :D
Ma se:

input = "a b c"
n = 1
target = "a"

quale dev'essere l'output???

Nel caso da te proposto l'output dovrebbe essere: "A b" ..allo stesso modo se:

input = "a b c"
n = 1
target = "c"


allora output = "b C"

Don[ITA]
11-03-2011, 17:10
Qualcosa del genere dovrebbe fare al caso tuo:

public static List<String> find(String input, String target, int n) {
List<String> results = new LinkedList<String>();
StringBuilder result;
String[] words = input.split(" ");
for(int i = 0; i < words.length; i++) {
if(words[i].equals(target)) {
result = new StringBuilder();
int min_index = i - n > 0 ? i - n : 0;
int max_index = i + n < words.length ? i + n : words.length - 1;
for(int j = min_index; j < max_index; j++) result.append(words[j] + " ");
result.append(words[max_index]);
results.add(result.toString());
}
}
return results;
}

Non credo sia la soluzione più performante per il tuo problema, ma fa quello che ti serve :D