I can't get the logic of this problem from my mind. Will you help me, pls?
I make a manual email validation for practice. So, in email validation there's a validation that states: "# is cannot be more than one."
I'm stuck from here:
int atValidation = 0;
for (int i = 0; i < txtEmail.Text.Length; i++)
{
if (Char.IsSymbol('#'))
{
atValidation++;
}
}
I'm sorry if my question is confusing, I can only explain like this vvv
Example:
Input Email |_______|
Input Email | rich#rd#aha.com |
message box: '#' cannot be more than one
Input Email | richard#aha.com |
message box: email is valid
There are many more rules for email validation, but if all you want to do is check for a single # sign, you could get all of the # characters and check the count
if (txtEmail.Text.ToCharArray().Where(x => x == '#').Count() != 1)
{
//email is invalid
}
There are other better ways to validate email for example MailAddress class and regex.
You can find examples here:
MailAddress:
Regex Email validation
regex:
Best Regular Expression for Email Validation in C#
There are a few ways you can do this. The first example I show below is a "straight" LINQ query and the second is an extension method that uses a loop. (Extension methods, in case you're not familiar, are a way of "adding" a method to class without modifying the original code; it's a Decorator Pattern).
LINQ Query approach:
int count = email.Count(c => c == '#');
This will give you the number of times that the '#' symbol appears. If count > 1 you know that there are duplicates. (Actually, you'd expect "count" to be exactly 1; if it's 0 there's no '#' symbol at all).
The downsides of the above solution are that it isn't very flexible (if you wanted to implement more rules you'd effectively be doing more loops, which isn't all that efficient) and that it'll always go through the entire string; it's not "smart enough" to know that it can stop counting once count == 2.
Here's another one:
public static class LinqExtensions
{
public static bool ContainsMultiple<T>(this IEnumerable<T> enumerable, T item)
{
bool seen = false;
foreach (T t in enumerable)
{
if (t.Equals(item))
{
if (seen) return true;
else seen = true;
}
}
return false;
}
}
You use it like this:
bool multiple = email.ContainsMultiple('#');
This solution also suffers from some degree of inflexibility (the only way to check multiple rules is to implement multiple loops/queries). However, it's "smart" enough to know that you can stop searching the string once you find a duplicate. It's also reusable.
You could also do:
Related
string[] words = new string[5] { "abbey","billowy", "chills","abced","abcde" };
it should display only:
abbey billowy chills abcde
I tried this code
List<string> AlphabeticOrder = new List<string>();
foreach (var word in words)
{
for (int i = 1; i < word.Length; i++)
{
if (word[i] < word[i - 1])
{
break;
}
AlphabeticOrder.Add(word);
break;
}
}
One line solution:
var alphabeticOrder = words.Where(w => Enumerable.SequenceEqual(w.OrderBy(x => x), w)).ToList();
EDIT: As pointed out in comments this approach is not the most optimal when it comes to the performance, so if this is a priority, one can consider solutions proposed in other answers.
This becomes easier if you break it into pieces. What you need is a function that takes a string and tells you if the characters in the string are in alphabetical order.
For example:
public static class CharacterSequence // I didn't think hard about the name
{
public static bool CharactersAreInAlphabeticalOrder(string input)
{
return input.SequenceEqual(input.OrderBy(c => c));
}
}
Having done that, the next part is just checking a collection of strings and returning only the ones where the characters are in order. If
A string is a collection of characters (char). This method takes the sequence of characters and sorts it. Then it compares the original to the sorted. If they are the same, then the original sequence was in order.
var wordsWithCharactersInOrder =
words.Where(CharacterSequence.CharactersAreInAlphabeticalOrder);
One reason why it's helpful to break it up like this is that it's easier to understand. It's very easy to read the above code and tell what it does. Also, if you realize that there's something you want to change about the way you check for characters in order, you can change that in the smaller function.
For example, you might realize that the original function is case-sensitive. C comes before d, but D comes before c. In this example it's less noticeable because the function is small, but as logic becomes more complex it's easier to read and think about when we break things into smaller functions. The case-insensitive version would be
public static bool CharactersAreInAlphabeticalOrder(string input)
{
var lowerCase = input.ToLower();
return lowerCase.SequenceEqual(lowerCase.OrderBy(c => c));
}
If you want to go a step further then you can compare the characters one at a time instead of sorting the entire string.
public static bool CharactersAreInAlphabeticalOrder(string input)
{
if (input.Length < 2) return true;
var lowerCase = input.ToLower();
var characterIndexes = Enumerable.Range(0, input.Length - 1);
return characterIndexes.All(characterIndex =>
lowerCase[characterIndex] <= lowerCase[characterIndex + 1]);
}
You can also write unit tests for it. If you know that the smaller function always returns the expected results, then the larger one that checks a collection of strings will return the correct results.
Here's an example of a unit test. It's much easier to test lots of conditions this way and have confidence that the function works than to edit the code and run it over and over. If you realize that there's another case you have to account for, you can just add it.
[DataTestMethod]
[DataRow("A", true)]
[DataRow("AB", true)]
[DataRow("abc", true)]
[DataRow("aBc", true)]
[DataRow("ba", false)]
public void CharactersAreInAlphabeticalOrder_returns_expected_result(string input, bool expected)
{
var result = CharacterSequence.CharactersAreInAlphabeticalOrder(input);
Assert.AreEqual(expected, result);
}
There was a small error in my original code. It didn't work if a word had only two letters. Without the test that error could have gone into the application without being noticed until later when it would take longer to find and fix. It's much easier with a test.
Words with letters in alphabetical order are known as abecedarian.
The difficulty in your algorithm is breaking out of a nested loop. There are different strategies to solve this problem:
Use a labeled statement and goto. Goto is frowned upon.
Use of a Boolean guard. This is okay but not very readable.
Place the inner loop into a method. This is the clean and easy to read solution that I decided to present.
Let us create a helper method:
private static bool IsAbecedarianWord(string word)
{
for (int i = 1; i < word.Length; i++) {
if (word[i] < word[i - 1]) {
return false;
}
}
return true;
}
With its help we can write:
foreach (var word in words) {
if (IsAbecedarianWord(word)) {
AlphabeticOrder.Add(word);
}
}
Clean and simple!
One note to naming conventions in C#. The usual conventions are (in short):
Type names, Method names and Property names are written in PascalCase. Interfaces are additionally prefixed with an upper case I (IPascalCase).
Names of method parameters and local variables are written in camelCase.
Field names (class and struct variables) are written in _camelCase with a leading underscore.
With that in mind, I suggest renaming AlphabeticOrder to abecedarian.
If you want to use your method try adding this:
foreach (var word in words)
{
for (int i = 1; i < word.Length; i++)
{
if (word[i] < word[i - 1])
{
break;
}
if (i == word.Length - 1)
{
AlphabeticOrder.Add(word);
}
}
}
Problem in your code is that it checks first 2 letters and if they are in alphabetic order it adds them to list.
The reason this is not working as expected is because the logic on whether to discard a result is flawed. The for loop which iterates the letters within the word is only checking the first letter and then exiting the loop regardless of the result.
I've added comments to your function below to help explain this.
for (int i = 1; i < word.Length; i++)
{
if (word[i] < word[i - 1]) // check the 2nd letter of the word against the 1st
{
break; // if the 2nd letter comes before the 1st in the alphabet, exit
}
AlphabeticOrder.Add(word); // add the word to the list
break; // exit the for loop
}
You should refactor the code such that it checks every letter of the word before adding it to the list of alphabetical words. You can also still end the for loop early if the condition fails.
There's a few ways to solve this, you could track the letters like Adam's answer above. Another possibility is to sort the array of letters and compare it to the original. If the arrays match then it's an alphabetical word for your scenario, if no match then it's not.
E.g.
foreach (var word in words)
{
var letters = word.ToList();
var sorted = word.OrderBy(l => l);
if (letters.SequenceEqual(sorted))
{
AlphabeticOrder.Add(word);
}
}
Which outputs:
abbey,billowy,chills,abcde
Logic is flawed.
Condition is satisfied in the first 2 letters and immediately added to the list.
List<string> AlphabeticOrder = new List<string>();
bool isOrdered = true; // Added this
foreach (var word in words)
{
isOrdered = true; // Added this
for (int i = 1; i < word.Length; i++)
{
if (word[i] < word[i - 1])
{
isOrdered = false; // Added this
break;
}
}
// Added this
if(isOrdered)
AlphabeticOrder.Add(word);
}
I'm making a game with character attributes, like strength, agility, etc. I have them all in a <string, double> dictionary. I need to implement "mods" to attributes from equipment, buffs, etc. I'd like to replace all instances of "CurrentStats[Key]" with a function(string input) of some sort, via Find/Replace. (I have HUNDREDS of references to it, I can't do that all by hand)
So basically, I'm looking for a way to write a function where I can somehow write
Function("Strength") = 5; for assignment
while still being able to use
if(Function("Strength") == 5) for fetching.
Is this possible?
Visual Studio has inbuilt regular expressions in its search and replace. You just need to enable the option when doing your replace.
You can probably just perform a global search and replace of something like CurrentStats\[([^\]]+)\] to MyFunction($1).
Explanation: this searches for the literal string CurrentStats[], with the content between the two brackets being a group (referenced in the replace as $1), indicated by having it surrounded by ( and ), containing [^\]]+, or, "a character group of anything that's not the closing quote ], repeated one or more times".
Note that this won't work if the key itself could contains something like myArray[i] since then it'll obviously match the closing bracket of that. Regex isn't really good at doing matching brackets or tags.
The locigcal approach would be to have a class for your character. You can use properties. Functions are usually called with arguments if you want to assign something, but properties can be assigned directly.
public class Character {
private bool overpowered = false;
private int _strength = 0;
public int Strength
{
get { return this._strength; }
set {
if (value > 10) { overpowered = true; }
this._strength = value;
}
}
// [...]
}
Then to use the property simple access it via the object:
Character c = new Character();
c.Strength = 5;
if (c.Strength == 5) { /* ... */ }
Using a dictionary makes little sense here.
It looks like ref returns are what I was after. I don't know how to mark this as answered. First post here. Thanks everyone
So I am looking to find a more effective way to determine all variants of the strings in the array in this this C# code I wrote. I could loop over the whole string and compare each character in sqltext to the one before it and make it overly complicated or i could try to learn something new. I was thinking there has to be a more efficient way. I showed this to a co-worker and she suggested I use a regular expression. I have looked into regular expressions a little bit, but i cant seem to find the right expression.
what I am looking for is a version that takes all variants of the indexes of the array in this code:
public bool securitycheck(String sqltext)
{
string[] badSqlList = new string[] {"insert","Insert","INSERT",
"update","Update","UPDATE",
"delete","Delete","DELETE",
"drop","Drop", "DROP"};
for (int i = 0; i < badSqlList.Count(); i++)
{
if (sqltext.Contains(badSqlList[i]) == true)
{
return true;
}
}
return false;
}
but takes into account for alternate spelling. this code for example does not take into account for "iNsert, UpDate, dELETE, DrOP" but according to my coworker there is a way using Regular expressions to take into account for this.
What is the best way to do this in your opinion?
[Update]
thank you everyone, there is lots of really good information here and it really does open my eyes to handling SQL programatically. the scope on this tool I am building is very small and anyone with the permissions to access this tool and who has intent on being malicious would be someone who has direct access to the database anyway. these checks are in place to more or less prevent laziness. The use-case does not permit for parameterized queries or i would be doing that. your insight has been very educational and I appreciate all your help!
You can do:
if (badSqlList.Any(r => sqltext.IndexOf(r, StringComparison.InvariantCultureIgnoreCase) >= 0))
{
//bad SQL found
}
IndexOf with StringComparison enum value will ensure case insensitive comparison.
Another approach could be:
return sqltext.Split()
.Intersect(badSqlList,StringComparer.InvariantCultureIgnoreCase)
.Any()
Split your Sql on white space and then compare each word with your white list array. This could save you in cases where your legal table name has keyword like INESRTEDStudents
Not really sure about your requirements, but, generally, a better option would be to use Parameterized queries in the first place. You can't be 100% sure with your white list and there still would be ways to bypass it.
Do not reinvent the wheel - just use parameterized queries as everyone here tells you (fixes even more problem than you are currently aware), you'll thank as all in the future...
But do use this to sanitaze all your filter strings that go in WHERE clauses:
public static string EscapeSpecial(string s)
{
Contract.Requires(s != null);
var sb = new StringBuilder();
foreach(char c in s)
{
switch(c)
{
case '[':
case ']':
case '%':
case '*':
{
sb.AppendFormat(CultureInfo.InvariantCulture, "[{0}]", c);
break;
}
case '\'':
{
sb.Append("''");
break;
}
default:
{
sb.Append(c);
break;
}
}
}
return sb.ToString();
}
Please note, the 'C#' tag was included intentionally, because I could accept C# syntax for my answer here, as I have the option of doing this both client-side and server-side. Read the 'Things You May Want To Know' section below. Also, the 'regex' tag was included because there is a strong possibility that the use of regular expressions is the best approach to this problem.
I have the following highlight Plug-In found here:
http://johannburkard.de/blog/programming/javascript/highlight-javascript-text-higlighting-jquery-plugin.html
And here is the code in that plug-in:
/*
highlight v4
Highlights arbitrary terms.
<http://johannburkard.de/blog/programming/javascript/highlight-javascript-text-higlighting-jquery-plugin.html>
MIT license.
Johann Burkard
<http://johannburkard.de>
<mailto:jb#eaio.com>
*/
jQuery.fn.highlight = function(pat) {
function innerHighlight(node, pat) {
var skip = 0;
if (node.nodeType == 3) {
var pos = node.data.toUpperCase().indexOf(pat);
if (pos >= 0) {
var spannode = document.createElement('span');
spannode.className = 'highlight';
var middlebit = node.splitText(pos);
var endbit = middlebit.splitText(pat.length);
var middleclone = middlebit.cloneNode(true);
spannode.appendChild(middleclone);
middlebit.parentNode.replaceChild(spannode, middlebit);
skip = 1;
}
}
else if (node.nodeType == 1 && node.childNodes && !/(script|style)/i.test(node.tagName)) {
for (var i = 0; i < node.childNodes.length; ++i) {
i += innerHighlight(node.childNodes[i], pat);
}
}
return skip;
}
return this.length && pat && pat.length ? this.each(function() {
innerHighlight(this, pat.toUpperCase());
}) : this;
};
jQuery.fn.removeHighlight = function() {
return this.find("span.highlight").each(function() {
this.parentNode.firstChild.nodeName;
with (this.parentNode) {
replaceChild(this.firstChild, this);
normalize();
}
}).end();
};
This plug-in works pretty easily.
If I wanted to highlight all instances of the word "Farm" within the following element...(cont.)
<div id="#myDiv">Farmers farm at Farmer's Market</div>
...(cont.) all I would need to do is use:
$("#myDiv").highlight("farm");
And then it would highlight the first four characters in "Farmers" and "Farmer's", as well as the entire word "farm" within the div#myDiv
No problem there, but I would like it to use this:
$("#myDiv").highlight("Farmers");
And have it highlight both "Farmers" AND "Farmer's". The problem is, of course, that I don't know the value of the search term (The term "Farmers" in this example) at runtime. So I would need to detect all possibilities of no more than one apostrophe at each index of the string. For instance, if I called $("#myDiv").highlight("Farmers"); like in my code example above, I would also need to highlight each instance of the original string, plus:
'Farmers
F'armers
Fa'rmers
Far'mers
Farm'ers
Farme'rs
Farmer's
Farmers'
Instances where two or more apostrophes are found sid-by-side, like "Fa''rmers" should, of course, not be highlighted.
I suppose it would be nice if I could include (to be highlighted) words like "Fa'rmer's", but I won't push my luck, and I would be doing well just to get matches like those found in my bulleted list above, where only one apostrophe appears in the string, at all.
I thought about regex, but I don't know the syntax that well, not to mention that I don't think I could do anything with a true/false return value.
Is there anyway to accomplish what I need here?
Things You May Want To Know:
The highlight plug-in takes care of all the case insensitive requirements I need, so no need to worry about that, at all.
Syntax provided in JavaScript, jQuery, or even C# is acceptable, considering the hidden input fields I use the values from, client-side, are populated, server-side, with my C# code.
The C# code that populates the hidden input fields uses Razor (i.e., I am in a C#.Net Web-Pages w/ WebMatrix environment. This code is very simple, however, and looks like this:
for (var n = 0; n < searchTermsArray.Length; n++)
{
<input class="highlightTerm" type="hidden" value="#searchTermsArray[n]" />
}
I'm copying this answer from your earlier question.
I think after reading the comments on the other answers, I've figured out what it is you're going for. You don't need a single regex that can do this for any possible input, you already have input, and you need to build a regex that matches it and its variations. What you need to do is this. To be clear, since you misinterpreted in your question, the following syntax is actually in JavaScript.
var re = new RegExp("'?" + "farmers".split("").join("'?") + "'?", "i")
What this does is take your input string, "farmers" and split it into a list of the individual characters.
"farmers".split("") == [ 'f', 'a', 'r', 'm', 'e', 'r', 's' ]
It then stitches the characters back together again with "'?" between them. In a regular expression, this means that the ' character will be optional. I add the same particle to the beginning and end of the expression to match at the beginning and end of the string as well.
This will create a regex that matches in the way you're describing, provided it's OK that it also matches the original string.
In this case, the above line builds this regex:
/'?f'?a'?r'?m'?e'?r'?s'?/
EDIT
After looking at this a bit, and the function you're using, I think your best bet will be to modify the highlight function to use a regex instead of a straight string replacement. I don't think it'll even be that hard to deal with. Here's a completely untested stab at it.
function innerHighlight(node, pat) {
var skip = 0;
if (node.nodeType == 3) {
var matchResult = pat.exec(node.data); // exec the regex instead of toUpperCase-ing the string
var pos = matchResult !== null ? matchResult.index : -1; // index is the location of where the matching text is found
if (pos >= 0) {
var spannode = document.createElement('span');
spannode.className = 'highlight';
var middlebit = node.splitText(pos);
var endbit = middlebit.splitText(matchResult[0].length); // matchResult[0] is the last matching characters.
var middleclone = middlebit.cloneNode(true);
spannode.appendChild(middleclone);
middlebit.parentNode.replaceChild(spannode, middlebit);
skip = 1;
}
}
else if (node.nodeType == 1 && node.childNodes && !/(script|style)/i.test(node.tagName)) {
for (var i = 0; i < node.childNodes.length; ++i) {
i += innerHighlight(node.childNodes[i], pat);
}
}
return skip;
}
What I'm attempting to do here is keep the existing logic, but use the Regex that I built to do the finding and splitting of the string. Note that I'm not doing the toUpper call anymore, but that I've made the regex case insensitive instead. As noted, I didn't test this at all, but it seems like it should be pretty close to a working solution. Enough to get you started anyway.
Note that this won't get you your hidden fields. I'm not sure what you need those for, but this will (if it's right) take care of highlighting the string.
How to find whether a string array contains some part of string?
I have array like this
String[] stringArray = new [] { "abc#gmail.com", "cde#yahoo.com", "#gmail.com" };
string str = "coure06#gmail.com"
if (stringArray.Any(x => x.Contains(str)))
{
//this if condition is never true
}
i want to run this if block when str contains a string thats completely or part of any of array's Item.
Assuming you've got LINQ available:
bool partialMatch = stringArray.Any(x => str.Contains(x));
Even without LINQ it's easy:
bool partialMatch = Array.Exists(stringArray, x => str.Contains(x));
or using C# 2:
bool partialMatch = Array.Exists(stringArray,
delegate(string x) { return str.Contains(x)); });
If you're using C# 1 then you probably have to do it the hard way :)
If you're looking for if a particular string in your array contains just "#gmail.com" instead of "abc#gmail.com" you have a couple of options.
On the input side, there are a variety of questions here on SO which will point you in the direction you need to go to validate that your input is a valid email address.
If you can only check on the back end, I'd do something like:
emailStr = "#gmail.com";
if(str.Contains(emailStr) && str.length == emailStr.length)
{
//your processing here
}
You can also use Regex matching, but I'm not nearly familiar enough with that to tell you what pattern you'd need.
If you're looking for just anything containing "#gmail.com", Jon's answer is your best bets.