How to compare inexact string values - c#

I want to compare two string values which are not exact For example I want to compare Admin to Administrator, this should return true or should execute.
I tried contain which is not working
var prodcut = lstProducts.Where(i => i.Name.ToLower().Contains(appname.ToLower())).FirstOrDefault();
Above code not working if i.Name is 'Admin' and appname.ToLower() is 'Administrator'. It just return null but want it should detect values.

If you want to check it both ways so if A contains B OR if B contains A you can use the || operator (the OR operator) like so:
a.Contains(b) || b.Contains(a)

You've got the strings the wrong way around (you're looking for Adminstrator in Admin)
You can do the check both ways around like this:
lstProducts.Where(i =>
i.Name.ToLower().Contains(appname.ToLower()) ||
appname.ToLower().Contains(i.Name.ToLower())
).FirstOrDefault();
Or just compare the first few characters:
lstProducts.Where(i =>
i.Name.ToLower().SubString(0,5) == appname.ToLower().SubString(0,5))
).FirstOrDefault();
Fuzzy matching is actually quite a complicated subject but there's a lot of research into the topic.

Related

Find a string in a list of strings in c#

I am trying to find if a list of strings contains a specific string in C#.
for example: Suppose I have 3 entries in my list
list<string> s1 = new List<string>(){
"the lazy boy went to the market in a car",
"tom",
"balloon"};
string s2 = "market";
Now I want to return true if s1 contains s2, which it does in this case.
return s1.Contains(s2);
This returns false which is not what I want. I was reading about Predicate but could not make much sense out of it for this case.
Thanks in advance.
The simplest way is to search each string individually:
bool exists = s1.Any(s => s.Contains(s2));
The List<string>.Contains() method is going to check if any whole string matches the string you ask for. You need to check each individual list element to accomplish what you want.
Note that this may be a time-consuming operation, if your list has a large number of elements in it, very long strings, and especially in the case where the string you're searching for either does not exist or is found only near the end of the list.
Contains' alternative could be IndexOf:
var res = s1.Any(s => s.IndexOf(s2, StringComparison.Ordinal) >= 0)
StringComparison.Ordinal passed as parameter because Contains() also use it internally.
Peter Duniho's answer is generally the best way. I am providing an alternate solution. This one does not require LINQ, lamdas, or loops. This only requires string built-in type's methods.
string.Concat(listOfString).Contains("data");
Note: This approach can lead to incorrect results. For example:
string.Concat("da", "ta").Contains("data");
will return true when it should be false;

C# Dynamic where for a collection

I want to search a collection based on text box. The user should be allowed to type in multiple words and in any order. Meaning if the string in the collection is "What a happy day" and the user types in "day What" the string should appear. Now I know how to do with with hard coding the number of words allowed (for example only 3 words allowed) with something like this;
nc = oc.Where(X => X.SearchData.IndexOf(words[0]) > -1 || X.SearchData.IndexOf(words[1]) > -1 || X.SearchData.IndexOf(words[2]) > -1);
note: yes I know I would have to protect to make sure there was actual 3 values in the array words but that is not shown.
The problem with this is that it limits the user and I don't want to do that. If the user wants to search off 10 or 20 things then that is fine with me.
Is there a way to dynamically create the Where statement for collection oc?
thanks
You need more LINQ:
oc.Where(x => words.Any(w => x.SearchData.IndexOf(w) > -1))
IndexOf(w) returns true even if w is a matched substring. For instance in your example if user enters Wha then it gets matched with What. As I understand you it is not the case. So you can simply split SearchData and search over it:
var enteredWords = SearchData.Split();
return oc.Where(p=> enteredWords.Any(q=>p.Contains(q));
I think the answer of #Slaks will match on partial words, as per my comment and the answer given by #Alireza
You could try
oc.Where(phrase => phrase.Split().Intersect(SearchData.Split()).Count() > 0);
There are always various ways with LINQ...

How is it possible to implement regular expressions (or the like) into WebMatrix razor C#?

I am trying to use regular expressions with my C# code, and I can find a few examples here on what those regular expressions might look like for my cause, but nowhere can I tell how I am supposed to (syntactically) implement that into my logic and code.
I have tried setting up an external .cs file and then calling the method, but the value returned is unable to be casted or worked with in any way.
The code can be found here:Checking strings for a strong enough password
In any event, I just want to know how I can check (and test against) values in a password to make sure it is up to standards that I specify.
A better way than suggesting to use regular expressions (since information on how to incorporate them into my own specific logistical setup is both very sparse and very confusing)
...is suggesting how it can be done without them.
I know I could use
foreach(char c in myString)
and then test individually, character by character, but I was hoping there was a better way that can either be regex, explained (that is, explained how to call this suggestion into action, not just posting a string of seemingly (but not) random characters and told, hey use that!), or not using regex at all, but somekind of shorthand, perhaps.
Truth is I would use regular expressions, but every time I look them up I can't seem to find anything that is useable by me in WebMatrix.
I want to be able to test a password to be sure that it has both an uppercase and a lowercase number. In addition I need to check for at least one number.
UPDATE:
Okay, allow me to rephrase my question, maybe I am being confusing...
How does regex work in webmatrix razor (C#). Please show how the regex actually works (I can't seem to find a clear, or even close to clear, answer on this on the web for webmatrix), then please show how it can be put (directly or indirectly) into if logic, on my cshtml page, so that I can actually check against it.
A Regular Expression (Regex), as you will find out, is a tool used in matching text against a pattern and even extracting or replacing matches in the source text.
To do this the Regex engine (which exists in the .Net framework inside the namespace System.Text.RegularExpressions) uses some established patterns that represent certain kinds of chars.
To use a Regex, you pass it the pattern agains which a text will be tested and the text itself.
For instance, the following snippet tests if there are lowercase letters in the text:
using System.Text.RegularExpressions;
...
var Pattern = "[a-z]";
if (Regex.IsMatch(SomeText, Pattern)) {
//... there is at least one lower case char in the text
}
The pattern used above estates that we are interested in a range of chars from lowercase "a" to lowercase "z".
A pattern to require at least one lowercase letter, one digit and one uppercase letter could probably be something like
#"[\d]+[a-z]+[A-Z]|[\d]+[A-Z]+[a-z]|[a-z]+[\d]+[A-Z]|[a-z]+[A-Z]+[\d]|[A-Z]+[\d]+[a-z]|[A-Z]+[a-z]+[\d]"
As you can see, a Regex pattern can be as simple as in the first example, but may escalate fast in complexity depending on the kind of information you want to check or extract.
In the Regex above, the items between square brackets are called character classes. The plus sign after an element is a quantifier, it indicates that the item may appear one or more times. Items separated by a vertical bar indicate alternatives. The "\d" pattern represents any digit from "0" to "9".
You don't really need a Regex to check the password strength in your application, but using then instead of the explicit tests you are currently making would (in my opinion), greatly improve your program's readability:
using System.Text.RegularExpressions;
...
if (!Regex.IsMatch(password, "[A-Z]")) {
errorMessage = "Your password must contain at least one uppercase character.";
} else if (!Regex.IsMatch(password, "[a-z]") {
errorMessage = "Your password must contain at least one lowercase character.";
} else if (! Regex.IsMatch(password, #"[\d]")){
errorMessage = "Your password must contain at least one numerical character.";
}
...
If you're trying to do this test on the page before the information is sent to the server, you can check with javascript and regex. I think this way is best, since you eliminate additional trips to the server. It can pass the javascript validation, post the data to your site, and you can validate more on the server (in case the user has javascript off). Razor syntax helps in the page rendering, but won't help you when the user is doing stuff on the page.
Pattern: ((?=.*\d)(?=.*[a-z])(?=.*[A-Z]).{8,15})
This is requiring at least 1 digit, 1 lowercase and 1 uppercase. It's also requiring the password to be between 8 and 15 characters long (inclusive). You can easily change the length requirements in the pattern. For example, if you wanted it to be at least 8 characters, but no max:
((?=.*\d)(?=.*[a-z])(?=.*[A-Z]).{8,})
To use this in javascript (I did use jQuery to wire up my click event in my test and get the password from the input):
var password = $('#password').val();
var pattern = /((?=.*\d)(?=.*[a-z])(?=.*[A-Z]).{8,15})/;
var pass = pattern.test(password);
A Fiddle showing it in action: http://jsfiddle.net/gromer/chF4D/1/
Well I know this isn't the way to properly do this, (the proper way is using regular expressions, which is what I was attempting to figure out) but if you are like me, and sick of asking/searching the same question over and over again, without getting any entirely useful feedback, this is what worked for me.
int Ucount = 0;
int Lcount = 0;
int Ncount = 0;
foreach(char c in password)
{
if(c!='A' && c!='B' && c!='C' && c!='D' && c!='E' && c!='F' && c!='G' && c!='H' && c!='I' && c!='J' && c!='K' && c!='L' && c!='M' && c!='N' && c!='O' && c!='P' && c!='Q' && c!='R' && c!='S' && c!='T' && c!='U' && c!='V' && c!='W' && c!='X' && c!='Y' && c!='Z')
{
Ucount++;
if(Ucount >= password.Length)
{
errorMessage = "Your password must contain at least one uppercase character.";
}
}
if(c!='a' && c!='b' && c!='c' && c!='d' && c!='e' && c!='f' && c!='g' && c!='h' && c!='i' && c!='j' && c!='k' && c!='l' && c!='m' && c!='n' && c!='o' && c!='p' && c!='q' && c!='r' && c!='s' && c!='t' && c!='u' && c!='v' && c!='w' && c!='x' && c!='y' && c!='z')
{
Lcount++;
if(Lcount >= password.Length)
{
errorMessage = "Your password must contain at least one lowercase character.";
}
}
if(c!='0' && c!='1' && c!='2' && c!='3' && c!='4' && c!='5' && c!='6' && c!='7' && c!='8' && c!='9')
{
Ncount++;
if(Ncount >= password.Length)
{
errorMessage = "Your password must contain at least one numerical character.";
}
}
}
Again, please note that the proper way to do this is to use regular expressions, but this code works fine for me, and I got to end the wild goose chase that was understanding regular expressions.
UPDATE:
Or, if you want to do it right, read Branco Medeiros's post above, he posted after I posted this, and his way is the right way to do it (provided you don't want to do it with JavaScript before it is sent to the server. If your app is like mine and not resource intensive enough to need JavaScript to do this, use Branco Medeiros's example above).

Is it possible to put two Lambda expressions inside a single query?

I was wondering if there is an easy way to place two Lambda expressions in a single (Linq/Where) query?
For example, I currently call a method with something like the following:
string testing = "blablabla";
if(testing == "" || testing == null)
I have tried a few combinations such as:
testing.Where(x => x == ("") || x=> x == null);
But the above doesn't work. I know I can set up a method that returns a predicate/bool, but, at the moment, I am interested in Lambdas and was just wondering how to achieve this.
Do I need to chain multiple Where methods, or is there a way to achieve multiple Lambdas?
(p.s. I know about IsNullOrEmpty, this is just the first example I could think of!)
You can always combine them to a single lambda.
testing.Where(x => x == null || x == ("") );
If you're looking for a general way to combine query conditions in arbitrary ways, you can use expression trees:
http://msdn.microsoft.com/en-us/library/bb882637.aspx

String-parsing-fu: Can you help me find a way to retrieve this value?

I need to somehow detect if there is a parent OU value, and if there is retrieve it.
For example, here there is no parent:
LDAP://servera/OU=Santa Cruz,DC=contoso,DC=com
But here, there is a parent:
LDAP://servera/OU=Ventas,OU=Santa Cruz,DC=contoso,DC=com
So I would need to retrieve that "Ventas" string.
Another example:
LDAP://servera/OU=Contabilidad,OU=Ventas,OU=Santa Cruz,DC=contoso,DC=com
I would need to retrieve that "Ventas" string as well.
Any suggestions on how to tackle this?
string ldap = "LDAP://servera/OU=Ventas,OU=Santa Cruz,DC=contoso,DC=com";
Match match = Regex.Match(ldap, #"LDAP://\w+/OU=(?<toplevelou>\w+?),OU=");
if(match.Success)
{
Console.WriteLine(match.Result("${toplevelou}"));
}
I'd find the first occurrence of OU=... and get it's value. Then I'd check if there was another occurrence after it. If so, return the value I've got. If not, return whatever it is you want if there's no parent (String.Empty, or, null, or whatever).
You could also use a regular express like this:
var regex = new Regex(#"OU=(.*?),");
var matches = regex.Matches(ldapString);
Then check how many matches there are. If >1 return the captured value from the first match.
Update
The regex above needs to be improved to allow the case where there's an escaped comma (\,) in the LDAP string. Maybe something like:
var regex = new Regex(#"OU=((.*?(\\\,)+?)+?),");
That may be broken, and there may be simpler way to do the same thing. I'm not a regex wizard.
Another Update
Per Kimberly's comment below the regex should be #"OU=((?:.*?(?:\\\,)*?)+?),".
Call me crazy, but I 'd do it this way (hey ma, look, an one-liner!):
var str = "LDAP://servera/OU=Ventas,OU=Santa Cruz,DC=contoso,DC=com";
var result = str.Substring(str.LastIndexOf('/') + 1).Split(',')
.Select(s => s.Split('='))
.Where(a => a[0] == "OU")
.Select(a => a[1])
.Reverse().Skip(1).FirstOrDefault();
result is either null or has the string you want. This will work no matter how many OUs are in there and return the second-to-last one, as long as the format of the string is valid to begin with.
Update: possible improvements:
The above will not work correctly if your DN contains an escaped forward slash or an escaped comma.
To fix both of these you need to use regular expressions. Change:
str.Substring(str.LastIndexOf('/') + 1).Split(',')
to:
Regex.Split(Regex.Split(str, "(?<!\\\\)/").Last(), "(?<!\\\\),")
What this does is separate the DN by getting the last part of str after splitting on forward slashes, and split the in parts DN by splitting on commas. In both cases, negative lookbehind is used to make sure that the slashes/commas are not escaped.
Not as pretty, I know. But it's still an one-liner (yay!) and it still allows you to use LINQ further down to handle multiple OUs any way you choose to.

Categories