Trying to do a keyword search but not sure how to use the contains method [modified]
-
I have a field in my database for tags the user can enter like "soda coke drinker or drinker soda coke ....." I understand I can find with contains
var results = from o in Database.Readall()
where o.tags.Contains(userTags)
select new .......Lets say I have in my database Customers a field called tags. Inside there it has coke drinker. then another field has coffee drinker A user comes along and wishes to find that record all drinkers i know i could do a customers.tags.contains(tags) and if they entered say drinker it would find both the coke drinker and the coffee drinker but what if they entered drinker coke or drinker coffee it would not find either one. because it would be looking for %drinker coke% or %drinker coffee% which doesn't exist in that order. How can you make it where it doesn't matter what order the words are in but actually checks to see if ANY of the words exist in that field ? an example would be great thanks
modified on Friday, February 26, 2010 8:40 AM
the .Contains() method is used to find items that Contain the specified "item". I would go for: 1) Predicate/Func or 2) A method like:
public bool MyContains(string tags, string user){
string[]separateWords = user.Split(" ");//just an example
foreach(var str in separateWords){
if(tags.Contains(str)){return true;}
}
return false;
}If 2) change your where clause to something like this:
where MyContains(o.tags, usewrTags)
-
the .Contains() method is used to find items that Contain the specified "item". I would go for: 1) Predicate/Func or 2) A method like:
public bool MyContains(string tags, string user){
string[]separateWords = user.Split(" ");//just an example
foreach(var str in separateWords){
if(tags.Contains(str)){return true;}
}
return false;
}If 2) change your where clause to something like this:
where MyContains(o.tags, usewrTags)
Thanks. I used method two and it works perfectly. I have one more question to ask. how would I I make it search where it contains both words? I see here it does a foreach on the split string and sees if it is inside the o.whatever and it works like it should if i enter say coke it finds everything that has coke in it. but if i specifically wanted the to display items containing where both the words exist in any sequence how would that be done ? Like if i have tags pizza coke drinker and another tag eggs coke and i enter in the search coke drinker. with the method you showed it would pull up both records. but i only want the one where BOTH words match? I'm sorry for all the questions this is really new to me. Thanks for your help.
-
Thanks. I used method two and it works perfectly. I have one more question to ask. how would I I make it search where it contains both words? I see here it does a foreach on the split string and sees if it is inside the o.whatever and it works like it should if i enter say coke it finds everything that has coke in it. but if i specifically wanted the to display items containing where both the words exist in any sequence how would that be done ? Like if i have tags pizza coke drinker and another tag eggs coke and i enter in the search coke drinker. with the method you showed it would pull up both records. but i only want the one where BOTH words match? I'm sorry for all the questions this is really new to me. Thanks for your help.
-
that's simple inverse the logic meaning
foreach(vat srt in words){
if (!tags.Contains(str)) {return false};
}
return true;//if it gets to this point means that it did not find a single word that is not
//contained in the tags so all of them were foundwell duh :( I feel really dumb on that one cause like you say that was simple. Thanks again for your help I really appreciate it.
-
well duh :( I feel really dumb on that one cause like you say that was simple. Thanks again for your help I really appreciate it.
-
no problem. And DONT feel dumb. I almost screw up my career some time ago because I felt dumb and did not have the patiance to read tones of documentation. But I didn't. Because other help me(not in here CP but you got the ideea) ;)
Thanks, I will take your advice. I read a lot but sometimes the examples are poor or simply wrong. Also, i have a hard time comprehending things (always have just a part of my life). Anyway, thanks for your kind words.
-
no problem. And DONT feel dumb. I almost screw up my career some time ago because I felt dumb and did not have the patiance to read tones of documentation. But I didn't. Because other help me(not in here CP but you got the ideea) ;)
Hey I know we have talked on this before. Still have an issue with it a little bit. What is happening is if i type in say lifeskills i will get a result for that. and also the match all works where if i typed in lifeskills christmas. That works perfectly the problem is it checks for the "whole word". Is there a way to check for instance if you type in lifeskill instead of lifeskills it will find it or if you type in say bear instead of bears ? here is what i have so far thanks for your previous help by the way...
public static IEnumerableGetbyKeywordLookup(string keywords) { var results = from o in BookProxy.Readall() //var results = from o in BookProxy.ReadallbyTags(keywords) where MyContains(o.TagName,keywords.Trim()) select new GridProxy { Author = string.Format("{0} {1}", o.AuthorFirstname, o.AuthorSurname), AuthorID = o.AuthorID, AuthorFirst = o.AuthorFirstname, AuthorSurname = o.AuthorSurname, TagID = o.TagID, BookID = o.bookID, ISBN = o.ISBN, BookNumber = o.RefNumber, BookTitle = o.Title, Count = BookNumberProxy.getall().Count(c => c.BOOK\_ID == o.bookID) }; printerlist = results.ToList(); var distinct = results.GroupBy(o => o.ISBN).Select(o => o.FirstOrDefault()); return distinct.ToList(); } public static IEnumerable GetbyKeywordLookupAll(string keywords) { var results = from o in BookProxy.Readall() where MyContainsAll(o.TagName, keywords.Trim()) select new GridProxy { Author = string.Format("{0} {1}", o.AuthorFirstname, o.AuthorSurname), AuthorID = o.AuthorID, AuthorFirst = o.AuthorFirstname, AuthorSurname = o.AuthorSurname, TagID = o.TagID, BookID = o.bookID, ISBN = o.ISBN,
-
Hey I know we have talked on this before. Still have an issue with it a little bit. What is happening is if i type in say lifeskills i will get a result for that. and also the match all works where if i typed in lifeskills christmas. That works perfectly the problem is it checks for the "whole word". Is there a way to check for instance if you type in lifeskill instead of lifeskills it will find it or if you type in say bear instead of bears ? here is what i have so far thanks for your previous help by the way...
public static IEnumerableGetbyKeywordLookup(string keywords) { var results = from o in BookProxy.Readall() //var results = from o in BookProxy.ReadallbyTags(keywords) where MyContains(o.TagName,keywords.Trim()) select new GridProxy { Author = string.Format("{0} {1}", o.AuthorFirstname, o.AuthorSurname), AuthorID = o.AuthorID, AuthorFirst = o.AuthorFirstname, AuthorSurname = o.AuthorSurname, TagID = o.TagID, BookID = o.bookID, ISBN = o.ISBN, BookNumber = o.RefNumber, BookTitle = o.Title, Count = BookNumberProxy.getall().Count(c => c.BOOK\_ID == o.bookID) }; printerlist = results.ToList(); var distinct = results.GroupBy(o => o.ISBN).Select(o => o.FirstOrDefault()); return distinct.ToList(); } public static IEnumerable GetbyKeywordLookupAll(string keywords) { var results = from o in BookProxy.Readall() where MyContainsAll(o.TagName, keywords.Trim()) select new GridProxy { Author = string.Format("{0} {1}", o.AuthorFirstname, o.AuthorSurname), AuthorID = o.AuthorID, AuthorFirst = o.AuthorFirstname, AuthorSurname = o.AuthorSurname, TagID = o.TagID, BookID = o.bookID, ISBN = o.ISBN,
Hy,
tonyonlinux wrote:
Is there a way to check for instance if you type in lifeskill instead of lifeskills it will find it or if you type in say bear instead of bears ?
Your methods are [Edit] NOT [/Edit] OK. [Edit] Don't split the tag(s) If you use
List.Contains(item)
it will call the Equals Method of the underling type in this case string. Ex:"Apples Oranges".Contains("Apple")=>true
"Apples Oranges".Contains("Orange")=>trueBut myList.Add("Apples");
myList.Add("Oranges");and then call
myList.Contains("Apple")
=>false[/Edit] Anyway: Suppose we have a tag of "My lions are eating lots of food". And user input "lion lot"; Well this code will find both of them and as a bonus return the hole word from tag => eg lions for lion and lots for lot.
string tag = "My lions are eating lots of food";
string user = "lion lot";List<String> matches = new List<string>();
string[] words = user.Split(' ');
foreach (var item in words)
{
if (tag.Contains(item))//it finds 'lion' in 'lions' and 'lot' in 'lots'
{
matches.Add(GetFullItem(tag, item));//returns the full word from the tags
//eg lions for lion...
}
}//and here's a GetFullItem
private string GetFullItem(string tag, string item)
{
//get start of the word (the location/index)
int idxStrat = tag.IndexOf(item);
//get the First Index of space after the start location for the current word
//=>the idxEnd
int idxEnd = tag.IndexOf(" ", idxStrat);
//now get the length
int length = idxEnd-idxStrat;
//finally return the hole string( eg lions instead of lion and lots instead of lot
return tag.Substring(idxStart,length);
}modified on Sunday, March 7, 2010 10:36 AM
-
Hy,
tonyonlinux wrote:
Is there a way to check for instance if you type in lifeskill instead of lifeskills it will find it or if you type in say bear instead of bears ?
Your methods are [Edit] NOT [/Edit] OK. [Edit] Don't split the tag(s) If you use
List.Contains(item)
it will call the Equals Method of the underling type in this case string. Ex:"Apples Oranges".Contains("Apple")=>true
"Apples Oranges".Contains("Orange")=>trueBut myList.Add("Apples");
myList.Add("Oranges");and then call
myList.Contains("Apple")
=>false[/Edit] Anyway: Suppose we have a tag of "My lions are eating lots of food". And user input "lion lot"; Well this code will find both of them and as a bonus return the hole word from tag => eg lions for lion and lots for lot.
string tag = "My lions are eating lots of food";
string user = "lion lot";List<String> matches = new List<string>();
string[] words = user.Split(' ');
foreach (var item in words)
{
if (tag.Contains(item))//it finds 'lion' in 'lions' and 'lot' in 'lots'
{
matches.Add(GetFullItem(tag, item));//returns the full word from the tags
//eg lions for lion...
}
}//and here's a GetFullItem
private string GetFullItem(string tag, string item)
{
//get start of the word (the location/index)
int idxStrat = tag.IndexOf(item);
//get the First Index of space after the start location for the current word
//=>the idxEnd
int idxEnd = tag.IndexOf(" ", idxStrat);
//now get the length
int length = idxEnd-idxStrat;
//finally return the hole string( eg lions instead of lion and lots instead of lot
return tag.Substring(idxStart,length);
}modified on Sunday, March 7, 2010 10:36 AM
so your are saying do this ?
private static bool MyContains(string tags, string user)
{List seperatewords = new List(user.Split(' ').ToList()); List seperateTags = new List(tags.Split(' ').ToList()); //new List matches = new List(); foreach (var str in seperatewords) { string stringvalue = str.ToString(); //new if (tags.Contains(str)) { matches.Add(GetfullText(tags, str)); } //end new //original if (seperateTags.Contains(str, StringComparer.CurrentCultureIgnoreCase)) { return true; } if (tags.Contains(matches.ToString(), StringComparer.CurrentCultureIgnoreCase)) { return true; } } return false; } private static string GetfullText(string tags, string str) { //get start of the word (the location/index) int idxStrat = tags.IndexOf(str); //get the First Index of space after the start location for the current word //=>the idxEnd int idxEnd = tags.IndexOf(" ", idxStrat); //now get the length int length = idxEnd - idxStrat; //finally return the hole string( eg lions instead of lion and lots instead of lot return tags.ToString().Substring(idxStrat, length); ; }
:( i'm confused still sorry
-
so your are saying do this ?
private static bool MyContains(string tags, string user)
{List seperatewords = new List(user.Split(' ').ToList()); List seperateTags = new List(tags.Split(' ').ToList()); //new List matches = new List(); foreach (var str in seperatewords) { string stringvalue = str.ToString(); //new if (tags.Contains(str)) { matches.Add(GetfullText(tags, str)); } //end new //original if (seperateTags.Contains(str, StringComparer.CurrentCultureIgnoreCase)) { return true; } if (tags.Contains(matches.ToString(), StringComparer.CurrentCultureIgnoreCase)) { return true; } } return false; } private static string GetfullText(string tags, string str) { //get start of the word (the location/index) int idxStrat = tags.IndexOf(str); //get the First Index of space after the start location for the current word //=>the idxEnd int idxEnd = tags.IndexOf(" ", idxStrat); //now get the length int length = idxEnd - idxStrat; //finally return the hole string( eg lions instead of lion and lots instead of lot return tags.ToString().Substring(idxStrat, length); ; }
:( i'm confused still sorry
No I, saying to do this:
private static bool MyContains(string tags, string user)
{
List seperatewords = new List(user.Split(' ').ToList());
//List seperateTags = new List(tags.Split(' ').ToList());//get rid of this
foreach (var str in seperatewords)
{
string stringvalue = str.ToString();
if (tags.Contains(str))
{
//matches.Add(...) this is optional just an example but you don't really need it
return true;
}
}
return false; -
No I, saying to do this:
private static bool MyContains(string tags, string user)
{
List seperatewords = new List(user.Split(' ').ToList());
//List seperateTags = new List(tags.Split(' ').ToList());//get rid of this
foreach (var str in seperatewords)
{
string stringvalue = str.ToString();
if (tags.Contains(str))
{
//matches.Add(...) this is optional just an example but you don't really need it
return true;
}
}
return false;thanks for your help but it is still not working. I tried what you posted above. but i get no results what so ever now. I think it has something to do with not having the stringcomparer.cultureignorecase in there. I tried to put it back in there but it doesn't like the fact that tags is not that of a list :(
-
No I, saying to do this:
private static bool MyContains(string tags, string user)
{
List seperatewords = new List(user.Split(' ').ToList());
//List seperateTags = new List(tags.Split(' ').ToList());//get rid of this
foreach (var str in seperatewords)
{
string stringvalue = str.ToString();
if (tags.Contains(str))
{
//matches.Add(...) this is optional just an example but you don't really need it
return true;
}
}
return false;nevermind i think i got it it looks like i did anyway when i ran some test. I simply took and did the following on the if statement.
if (tags.toUpper().Contains(str.ToUpper))
{
return true;
}thanks again
-
thanks for your help but it is still not working. I tried what you posted above. but i get no results what so ever now. I think it has something to do with not having the stringcomparer.cultureignorecase in there. I tried to put it back in there but it doesn't like the fact that tags is not that of a list :(
OK. Maybe I understood you wrong. Here's what I think you need to acomplish => correct me if I'm wrong. So, you need to get like all the data about books based on the book keywords/tags and the keywords introduced by user. If that's what you need then this is a working solution: (feel free to create a new windows app, add 2 buttons and paste the code to check):
/// <summary>
/// check if contains any keywords
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void btnContainsAny_Click(object sender, EventArgs e)
{
string tags = "science fiction futurist 1024 cores 25 GHz";
string user = "fiction core";
if (MyContainsAny(tags, user))
{
string message =
String.Format("At least one keyword form \"{0}\" was found in \r\n" +
"\"{1}\"", user, tags);
MessageBox.Show(message);
}
}/// <summary> /// check if contains all keywords /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void btnContainsAll\_Click(object sender, EventArgs e) { string tags = "science fiction futurist 1024 cores 25 GHz"; string user = "fiction core"; if (MyContainsAll(tags, user)) { string message = String.Format("All the keywords form \\"{0}\\" were found in \\r\\n" + "\\"{1}\\"", user, tags); MessageBox.Show(message);//as you can see it finds core in cores } } /// <summary> /// used to see if the tag contains ANY of the keywords introduced by user /// </summary> /// <param name="tag"></param> /// <param name="userData"></param> /// <returns></returns> private bool MyContainsAny(string tag, string userData) { string\[\] words = userData.Trim().Split(" "); foreach (var item in words) { if (tag.Contains(item)) { return true; } } return false; } /// <summary> /// used to see if the tag contains ALL of the keywords introduced by user /// </