|
|||||||
|
|
|
![]() |
|
|
Strumenti |
|
|
#1 |
|
Senior Member
Iscritto dal: Sep 2004
Messaggi: 3967
|
[C# - LinQ]Eseguire ricerca su stringhe
Ciao a tutti.
gli strumenti che ho a disposizione sono: sql server 2008, C# ed entity framework. Devo effettuare una ricerca su parole o porzioni di frasi, in questo modo: Codice:
var result = mioOggetto.Where(c => c.Meaning.Contains(parola)); Ciò che però non riesco a fare è passargli qualcosa di più complesso, ad esempio: supponendo che devo trovare tutto ciò che contiene "mario pippo paperopoli" o che almeno contenga uno di questi termini, quel metodo non mi è più sufficiente. per essere più chiaro: Codice:
//ho dei record che contengono ad esempio "TESTO1" "mario era andato da gigi per prendere un caffè" "TESTO2" "pippo abita a paperopoli che è una graziosa cittadina" "TESTO3" "mario andò con gigi a paperopoli dove fanno un ottimo caffè" Codice:
cerca: mario, gigi, cittadina, caffè o anche Codice:
cerca: mario andato caffè Grazie a tutti RaouL.
__________________
Dai wafer di silicio nasce: LoHacker... il primo biscotto Geek
|
|
|
|
|
|
#2 |
|
Senior Member
Iscritto dal: Aug 2003
Città: Barletta (BA)
Messaggi: 939
|
Non c'è bisogno di alcun codice personalizzato
var result = mioOggetto.Where(c => c.Meaning.Contains(parola) || c.Meaning.Contains(parola1) || c.Meaning.Contains(parola2)));
__________________
In a world without fences, who needs Gates? Power by: Fedora 8 - Mac OS X 10.4.11 |
|
|
|
|
|
#3 | |
|
Senior Member
Iscritto dal: Sep 2004
Messaggi: 3967
|
Quote:
Però.... io a monte non so l'utente quante parole digiterà nel campo di ricerca, quindi 'credo' che devo fare qualche passaggio in più.
__________________
Dai wafer di silicio nasce: LoHacker... il primo biscotto Geek
|
|
|
|
|
|
|
#4 |
|
Senior Member
Iscritto dal: Sep 2004
Messaggi: 3967
|
Ho un primo prototipo ma è molto lento:
Codice:
public BindingSource GetByMeanings(string meaning)
{
context = new EntityContext();
string[] strArray = meaning.Split(',');
BindingSource bs = new BindingSource();
foreach(string str in strArray)
{
var bList = context.DBOMeanings.Where(c => c.Contains(str));
localReportSource.DataSource = bList;
}
return localReportSource;
}
__________________
Dai wafer di silicio nasce: LoHacker... il primo biscotto Geek
|
|
|
|
|
|
#5 | |
|
Senior Member
Iscritto dal: Aug 2003
Città: Barletta (BA)
Messaggi: 939
|
Quote:
var result = mioOggetto.Where(c => listaParole.Any(c.Contains)); Per capire meglio listaParole.Any(c.Contains) http://www.ginktage.com/2011/03/usin...nversion-in-c/
__________________
In a world without fences, who needs Gates? Power by: Fedora 8 - Mac OS X 10.4.11 |
|
|
|
|
|
|
#6 | |
|
Senior Member
Iscritto dal: Sep 2004
Messaggi: 3967
|
Quote:
sto dando un occhio a quel link ma non mi è chiaro nulla, cioè: il mio oggetto è un'entità mappata su una tabella del db; "listaParole", è l'insieme di stringhe che prendo da una casella di testo, con il metodo Split(), per es.: "abc,caffè,barca" Qualsiasi cosa cerco di fare per "capire" l'esempio, non mi fa neanche compilare...
__________________
Dai wafer di silicio nasce: LoHacker... il primo biscotto Geek
|
|
|
|
|
|
|
#7 |
|
Senior Member
Iscritto dal: Aug 2003
Città: Barletta (BA)
Messaggi: 939
|
Quella non è altra che una forma abbreviata per scrivere:
var result = mioOggetto.Where(c => listaParole.Any(parola => c.Contains(parola))); E' strano che non ti fa compilare, controlla di che tipo è c Che errore ti da il compilatore?
__________________
In a world without fences, who needs Gates? Power by: Fedora 8 - Mac OS X 10.4.11 |
|
|
|
|
|
#8 |
|
Senior Member
Iscritto dal: Sep 2004
Messaggi: 3967
|
Beh... "c" dev'essere per forza di tipo "mioOggetto"
__________________
Dai wafer di silicio nasce: LoHacker... il primo biscotto Geek
|
|
|
|
|
|
#9 |
|
Senior Member
Iscritto dal: Aug 2003
Città: Barletta (BA)
Messaggi: 939
|
c dev'essere una stringa se vuoi che il codice scritto prima funzioni e mioOggetto una collezione di stringhe
__________________
In a world without fences, who needs Gates? Power by: Fedora 8 - Mac OS X 10.4.11 |
|
|
|
|
|
#10 | |
|
Senior Member
Iscritto dal: Sep 2004
Messaggi: 3967
|
Quote:
io sto facendo una ricerca su un oggetto che altro non è che la rappresentazione di una tabella nel db (mediante entity framework). Ho notato comunque che qualcosa non mi torna se uso banalmente linq to sql: Codice:
string[] listaParole = myText.Split(',');
var list = from c in contex.DBOMeanings
where listaParole.Contains(c.Meanings)
select c;
... beh... non trova nulla....
__________________
Dai wafer di silicio nasce: LoHacker... il primo biscotto Geek
|
|
|
|
|
|
|
#11 |
|
Senior Member
Iscritto dal: Sep 2004
Messaggi: 3967
|
al momento ho risolto un primo problema così:
Codice:
string[] listaParole = sometext.Split(,);
var query = context.DBOMeanings.ToList();
List<DBOMeanings> results = new List<DBOMeanings>();
foreach(var obj in query)
{
foreach(string s in listaParole)
{
if(obj.meaning.Contains(s))
{
results.Add(obj);
}
}
}
....tranne che per l'ordinamento dovrei ordinarli in modo che: cerco "piano,pavimento" se un record le contiene entrambe dev'essere il primo della lista e poi man mano quelli che ne contengono solo una...
__________________
Dai wafer di silicio nasce: LoHacker... il primo biscotto Geek
|
|
|
|
|
|
#12 |
|
Senior Member
Iscritto dal: May 2004
Città: Londra (Torino)
Messaggi: 3692
|
Ma e LinQ ?
Codice:
static void Main(string[] args)
{
const string sometext = "primo, secondo";
var tosearch = new[]
{
new {meaning = "quello che fa il primo", altroacaso = 2},
new {meaning = "non lo fa il secondo", altroacaso = 3},
new {meaning = "e il terzo non vedra'", altroacaso = 1},
new {meaning = "quello che il secondo e il primo faranno", altroacaso = 2},
new {meaning = "il quarto dorme", altroacaso = 2}
};
string[] listaParole = sometext.Split(",".ToCharArray(), StringSplitOptions.RemoveEmptyEntries);
// Primo risultato, complessita' O(N^2)
var results = from row in tosearch
from parola in listaParole
where row.meaning.Contains(parola)
let res = new {row, parola}
group res by row into grp
orderby grp.Count() descending
select grp.Key;
results.ToList().ForEach(Console.WriteLine);
Console.WriteLine("-------------");
Console.WriteLine();
Console.ReadKey();
// Secondo risultato, complessita' inferiore a O(N^2), probabilmente O(N)
// Vado di Regex, costruisco il pattern da cercare a partire dalla comma separated string di input
// Esempio: "(primo|secondo)"
string[] listaParoleNuova = sometext.Split(",".ToCharArray(), StringSplitOptions.RemoveEmptyEntries)
.Select(word => word.Trim())
.ToArray();
string joinedWithBar = string.Join("|", listaParoleNuova);
string regexPattern = string.Format("({0})", joinedWithBar);
var regex = new Regex(regexPattern, RegexOptions.Compiled);
var results2 = from row in tosearch
let matches = regex.Matches(row.meaning)
let count = matches.Count
where count > 0
orderby count descending
select row;
results2.ToList().ForEach(Console.WriteLine);
Console.WriteLine("-------------");
Console.ReadKey();
}
__________________
Se pensi che il tuo codice sia troppo complesso da capire senza commenti, e' segno che molto probabilmente il tuo codice e' semplicemente mal scritto. E se pensi di avere bisogno di un nuovo commento, significa che ti manca almeno un test. |
|
|
|
|
|
#13 |
|
Senior Member
Iscritto dal: Sep 2004
Messaggi: 3967
|
Ciao gugoXX
Ho solo un piccolo problema nell' "importare" la tua spiegazione alla mia problematica. Usando LinQ to Entity ottengo che: Codice:
LINQ to Entities does not recognize the method 'System.Text.RegularExpressions.MatchCollection Matches(System.String)' method, and this method cannot be translated into a store expression.
__________________
Dai wafer di silicio nasce: LoHacker... il primo biscotto Geek
|
|
|
|
|
|
#14 |
|
Senior Member
Iscritto dal: May 2004
Città: Londra (Torino)
Messaggi: 3692
|
Prova a commentare da
Secondo Risulato in poi.
__________________
Se pensi che il tuo codice sia troppo complesso da capire senza commenti, e' segno che molto probabilmente il tuo codice e' semplicemente mal scritto. E se pensi di avere bisogno di un nuovo commento, significa che ti manca almeno un test. |
|
|
|
|
|
#15 | |
|
Member
Iscritto dal: Nov 2009
Messaggi: 56
|
Quote:
quindi se è come sto pensando, nella tua soluzione Linq dei aggiungere uno di quei metodi, quindi una cosa del genere : Codice:
string[] listaParole = myText.Split(',');
var list = from c in contex.DBOMeanings.ToList()
where listaParole.Contains(c.Meanings)
select c;
__________________
Un elemento come me quando si fissa fa sempre un gran casino, ma solo nel 45 ciò è stato negativo . Little Boy era mio nonno |
|
|
|
|
|
|
#16 |
|
Senior Member
Iscritto dal: Sep 2004
Messaggi: 3967
|
Ok, senza usare le regex il tuo metodo funziona. Certo ho da lavorarci su
perchè ho qualche risultato che non mi aspetto, ma mi hai già praticamente fornito tutte le informazioni necessarie per risolverlo. @U235 E' già tutto caricato, non ho incollato solo il pezzo di codice che riguarda il load.
__________________
Dai wafer di silicio nasce: LoHacker... il primo biscotto Geek
|
|
|
|
|
|
#17 |
|
Member
Iscritto dal: Nov 2009
Messaggi: 56
|
Ciao,
una cosa del genere ? Codice:
List<MiaTabella> MiaTabella = new List<MiaTabella>();
MiaTabella.Add(new MiaTabella() { AltroCampo = "123456", Messaggio = "mario era andato da gigi per prendere un caffè" });
MiaTabella.Add(new MiaTabella() { AltroCampo = "123456", Messaggio = "pippo abita a paperopoli che è una graziosa cittadina" });
MiaTabella.Add(new MiaTabella() { AltroCampo = "123456", Messaggio = "mario andò con gigi a paperopoli dove fanno un ottimo caffè" });
List<string> Parole = new List<string>();
Parole = new List<string>();
Parole.Add("mario");
Parole.Add("gigi");
//Parole.Add("cittadina");//se aggiungi questa ti trova anche la seconda
Parole.Add("caffè");
MiaTabella = MiaTabella.Where(w => w.Messaggio.Split(' ').Any(p => Parole.Select(c => c.ToUpper()).Contains(p.ToUpper()))).ToList();
__________________
Un elemento come me quando si fissa fa sempre un gran casino, ma solo nel 45 ciò è stato negativo . Little Boy era mio nonno |
|
|
|
|
|
#18 |
|
Member
Iscritto dal: Nov 2009
Messaggi: 56
|
se poi volessi ad esempio avere in un altro campo le parole che sono state trovarte nella frase, allora potresti fare una cosa del genere :
Codice:
List<MiaTabella> MiaTabella = new List<MiaTabella>();
MiaTabella.Add(new MiaTabella() { Parole = new MiaListaString(), Messaggio = "mario era andato da gigi per prendere un caffè" });
MiaTabella.Add(new MiaTabella() { Parole = new MiaListaString(), Messaggio = "pippo abita a paperopoli che è una graziosa cittadina" });
MiaTabella.Add(new MiaTabella() { Parole = new MiaListaString(), Messaggio = "mario andò con gigi a paperopoli dove fanno un ottimo caffè" });
List<string> Parole = new List<string>();
Parole = new List<string>();
Parole.Add("mario");
Parole.Add("gigi");
Parole.Add("cittadina");//se aggiungi questa ti trova anche la seconda
Parole.Add("caffè");
MiaTabella = MiaTabella.Where(
w => w.Messaggio.Split(' ')
.Where(p => Parole.Select(c => c.ToUpper()).Contains(p.ToUpper()))
.Select(sw => w.Parole.AddString(sw)).ToList().Any()).ToList();
Codice:
public class MiaTabella
{
public string Messaggio { get; set; }
public MiaListaString Parole { get; set; }
}
public class MiaListaString : List<string>
{
public bool AddString(string item)
{
base.Add(item);
return true;
}
}
il risultato che avresti sarebbe : MiaTabella[0].Messaggio = "mario era andato da gigi per prendere un caffè" MiaTabella[0].Parole = [0] = "mario" [1] = "gigi" [2] = "caffè" //questo solo se c'è tra le parole anche "cittadina" MiaTabella[1].Messaggio = "pippo abita a paperopoli che è una graziosa cittadina" MiaTabella[1].Parole = [0] = "cittadina" MiaTabella[2].Messaggio = "mario andò con gigi a paperopoli dove fanno un ottimo caffè" MiaTabella[2].Parole = [0] = "mario" [1] = "gigi" [2] = "caffè" ma almeno avevo capito bene ciò che ti serviva? ![]() EDIT : non avevo letto dell'ordinamento ![]() Codice:
MiaTabella = MiaTabella.Where(
w => w.Messaggio.Split(' ')
.Where(p => Parole.Select(c => c.ToUpper()).Contains(p.ToUpper()))
.Select(sw => w.Parole.AddString(sw)).ToList().Any())
.OrderByDescending(o=>o.Parole.Count).ToList();
MiaTabella[0].Messaggio = "mario era andato da gigi per prendere un caffè" MiaTabella[0].Parole = [0] = "mario" [1] = "gigi" [2] = "caffè" MiaTabella[1].Messaggio = "mario andò con gigi a paperopoli dove fanno un ottimo caffè" MiaTabella[1].Parole = [0] = "mario" [1] = "gigi" [2] = "caffè" //questo solo se c'è tra le parole anche "cittadina" MiaTabella[2].Messaggio = "pippo abita a paperopoli che è una graziosa cittadina" MiaTabella[2].Parole = [0] = "cittadina"
__________________
Un elemento come me quando si fissa fa sempre un gran casino, ma solo nel 45 ciò è stato negativo . Little Boy era mio nonno Ultima modifica di U235 : 18-03-2012 alle 01:21. |
|
|
|
|
|
#19 |
|
Member
Iscritto dal: Nov 2009
Messaggi: 56
|
se poi volessi ordinare per numero di occorrenze DIFFERENTI tra loro in primo luogo e in secondo luogo numero di occorrenze in generale (anche doppioni, allora potresti fare questo :
Codice:
MiaTabella = MiaTabella.Where(
w => w.Messaggio.Split()
.Where(p => Parole.Select(c => c.ToUpper()).Contains(p.ToUpper()))
.Select(sw => w.Parole.AddString(sw)).ToList().Any())
.OrderByDescending(o=>o.Parole.Count)
.OrderByDescending(o2 => o2.Parole.Distinct().Count())
.ToList();
Codice:
MiaTabella.Add(new MiaTabella() { Parole = new MiaListaString(), Messaggio = "cittadina mario era andato da gigi per prendere un caffè" });
MiaTabella.Add(new MiaTabella() { Parole = new MiaListaString(), Messaggio = "gigi pippo abita a paperopoli che è una graziosa cittadina" });
MiaTabella.Add(new MiaTabella() { Parole = new MiaListaString(), Messaggio = "gigi gigi gigi gigi gigi pippo abita a paperopoli che è una graziosa cittadina" });
MiaTabella.Add(new MiaTabella() { Parole = new MiaListaString(), Messaggio = "gigi mario andò con gigi a paperopoli dove fanno un ottimo caffè" });
MiaTabella[0].Messaggio = "cittadina mario era andato da gigi per prendere un caffè" MiaTabella[0].Parole = [0] = "cittadina" [1] = "mario" [2] = "gigi" [3] = "caffè" MiaTabella[1].Messaggio = "gigi mario andò con gigi a paperopoli dove fanno un ottimo caffè" MiaTabella[1].Parole = [0] = "gigi" [1] = "mario" [2] = "gigi" [3] = "caffè" MiaTabella[2].Messaggio = "gigi gigi gigi gigi gigi pippo abita a paperopoli che è una graziosa cittadina" MiaTabella[2].Parole = [0] = "gigi" [1] = "gigi" [2] = "gigi" [3] = "gigi" [4] = "gigi" [5] = "cittadina" MiaTabella[3].Messaggio = "pippo abita a paperopoli che è una graziosa cittadina" MiaTabella[3].Parole = [0] = "gigi" [1] = "cittadina" ciao. P.S. mi hai dato una "spinta" per fare una cosa che mi serviva, spero ti sia utile anche a te
__________________
Un elemento come me quando si fissa fa sempre un gran casino, ma solo nel 45 ciò è stato negativo . Little Boy era mio nonno |
|
|
|
|
|
#20 |
|
Senior Member
Iscritto dal: Sep 2004
Messaggi: 3967
|
@U235:
Ciao e grazie anche a te per il prezioso aiuto ! La tua idea funziona bene se resto nei limiti di circa 10.000 record. Passando oltre, non ho ancora capito il perchè, mi succede questo: 1) Mi trova corrispondenze che non sono nei termini di ricerca 2) La ricerca diventa molto lenta, considerando che agisce su una tabella contenente poco meno di un milione di records. Oggi devo fare altri test e posso riportare qualcosa di più preciso. RaouL.
__________________
Dai wafer di silicio nasce: LoHacker... il primo biscotto Geek
|
|
|
|
|
| Strumenti | |
|
|
Tutti gli orari sono GMT +1. Ora sono le: 01:13.





















