Optimize string comparison in C# - c#

I have the following code on an asp.net button click
if(str == ipaddr1 || ipaddr2 || ipaddr3 || ipaddr4 || ipaddr5 || ipaddr6 || ipaddr7)
// do this
else
//cancel click event
How can I optimize this piece of code?
Update: Apologies everyone! I did not mean to compare it with the literal string ipaddr. I mean to compare it to the value ipaddr1, ipaddr2 holds and so on

replace with:
Regex.IsMatch(str, "^ipaddr[1-7]$")
Optimised for readability not necessarily performance.

HashSet<T> is the best container to check containing:
var ips = new HashSet<string> { "ip1", "ip2", "ip3", "ip4", "ip5" };
if (ips.Contains(input))
{
// do stuff
}
For any type:
var ips = new HashSet<IPHostEntry> { ip1, ip2, ip3, ip4, ip5 };
if (ips.Contains(input))
{
// do stuff
}
Was:
if(str = qry.StartsWith("23.55") || str = qry.StartsWith("xuz") || str = qry.StartsWith("i3") || str = qry.StartsWith("i444") || str = qry.StartsWith("ki5") || str = qry.StartsWith("65fr6")) // do this else // do this
Become:
var arr = new[] { "23.55", "xuz", "i3", "i444", "ki5", "65fr6") };
if (arr.Any(str => input.StartsWith(str, StringComparison.Ordinal))
{
// do stuff
}
StringComparison.Ordinal or StringComparison.OrdinalIgnoreCase are very important for performance.

What about
if(str.Substring(0,6) == "ipaddr" && str[6] >= '1' && str[6] <= '7')
For your information, your original code does not even compile. This
if(str == "ipaddr1" || "ipaddr2" || "ipaddr3" || "ipaddr4" || "ipaddr5" || "ipaddr6" || "ipaddr7")
Needs to be replaced with this to compile
if(str == "ipaddr1" || str == "ipaddr2" || str == "ipaddr3" || str == "ipaddr4" || str == "ipaddr5" || str == "ipaddr6" || str == "ipaddr7")
So the original code is actually even more tedious than you thought.
UPDATE
According to your updated question, the best option is to put your string variables into a List<string> called, for example ipaddr. Then to see if the string str is included, simply do this:
if( ipaddr.Contains( str ) )
{
//contained in the list
}

I would do something like:
str.Length == 7 && str.StartsWith("ipaddr") && str[6] > '0' && str[6] < '8'
Edit:
After your update, I would do something like:
string[] validStrings = { ipaddr1, ipaddr2, ... };
bool isStrValid = validStrings.Contains(str);
For better performance, consider using a HashSet<string> instead of an array, especially if the list of valid strings doesn't change.

Both more readable, and more performant would be:
switch(str)
{
case "ipaddr1":
case "ipaddr2":
case "ipaddr3":
case "ipaddr4":
case "ipaddr5":
case "ipaddr6":
case "ipaddr7":
//do something
break;
default:
//do something else
break;
}
(although, admittedly massively verbose...)

I would do a
List<string> variables = new List<string> { "ip1","ip2","ip3","ip4","ip5" };
if (variables.Contains(inputstring))
...

Related

How to check for special characters in a string using a loop

since my prof won't let me use RegEx, I'm stuck with using loops to check each character on a string.
Does anyone have a sample code/algorithm?
public void setAddress(string strAddress)
{
do
{
foreach (char c in Name)
{
if ( /*check for characters*/ == false)
{
Address = strAddress;
}
}
if ( /*check for characters*/ == true)
{
Console.Write("Invalid!");
}
} while ( /*check for characters*/ == true)
}
public int getAddress()
{
return Address;
}
I need to only include letters and numbers. Characters such as !##$%^& are not allowed.
I'm not allowed to use RegEx because he hasn't taught that to us yet... well I couldn't attend class on the day he taught these loops and character checking, so now he won't tell me more. ANYWAY, if there's a more efficient way without using RegEx, that'd be helpful.
string s = #"$KUH% I*$)OFNlkfn$";
var withoutSpecial = new string(s.Where(c => Char.IsLetterOrDigit(c)
|| Char.IsWhiteSpace(c)).ToArray());
if (s != withoutSpecial)
{
Console.WriteLine("String contains special chars");
}
You can do it without loops at all :)
Source: https://stackoverflow.com/a/4503614/1714342
EDIT:
if(s.Any(c=>c => !Char.IsLetterOrDigit(c) || !Char.IsWhiteSpace(c))
{
Console.WriteLine("String contains special chars");
}
You may not need loops at all, just character checking will do:
if (Name.IndexofAny("!##$%^&*()".ToCharArray() != -1))
Console.WriteLine("Valid Address");
else
Console.WriteLine("Invalid Address");
See http://msdn.microsoft.com/en-us/library/system.string.indexofany.aspx
A solution with explicit loop could be
String s = #"$KUH% I*$)OFNlkfn$";
foreach (Char c in s)
if (!(Char.IsLetterOrDigit(c) || Char.IsWhiteSpace(c))) {
Console.WriteLine("String contains special chars");
break;
}
bool check_for_characters(char c)
{
return (c >= '0' && c <= '9') || (c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z');
}

Can't understand why if statement is running code for True test result

I have an IF statement that is supposed to make sure the TextBox1.Text and TextBox2.Text do not match or are not blank. If they don't match or are not blank then it is supposed to assign the text in the boxes to two string variable. What I can't figure out is why when I leave the two textboxes blank the true statement still fires.
if ((tbStartBreak2.Text != tbEndBreak2.Text) || (tbStartBreak2.Text == "" && tbEndBreak2.Text == ""))
{
sb2 = tbStartBreak2.Text;
se2 = tbStartBreak2.Text;
}
There are two conditions in your if statement:
if ((tbStartBreak2.Text != tbEndBreak2.Text) || (tbStartBreak2.Text == "" && tbEndBreak2.Text == ""))
The first one checks to make sure they don't match (so, good). The second checks to make sure that they are blank (so, bad). You want this:
if ((tbStartBreak2.Text != tbEndBreak2.Text) || (tbStartBreak2.Text != "" && tbEndBreak2.Text != ""))
Also, what are you trying to do? The second condition is the only one you need if you really want them not to match OR not be blank - because the only time this will be false is if they are both blank.
You wrote "OR textbox are blank", you need "OR textbox are not blank"
if ((tbStartBreak2.Text != tbEndBreak2.Text) || (tbStartBreak2.Text != "" && tbEndBreak2.Text != ""))
{
sb2 = tbStartBreak2.Text;
se2 = tbStartBreak2.Text;
}
As a side note, I'd replace "" with string.Empty for readability.
if ((tbStartBreak2.Text != tbEndBreak2.Text) || (tbStartBreak2.Text != string.Empty && tbEndBreak2.Text != string.Empty))
{
sb2 = tbStartBreak2.Text;
se2 = tbStartBreak2.Text;
}
And for even more readability, you can extract these big conditions
if (TextboxesDoNotMatch() || TextboxesAreNotEmpty())
{
sb2 = tbStartBreak2.Text;
se2 = tbStartBreak2.Text;
}
private bool TextboxesDoNotMatch()
{
return tbStartBreak2.Text != tbEndBreak2.Text;
}
private bool TextboxesAreNotEmpty()
{
return tbStartBreak2.Text != string.Empty && tbEndBreak2.Text != string.Empty;
}
If you want it to return that they are NOT blank then you need to do this
(tbStartBreak2.Text != "" && tbEndBreak2.Text != "")
you have an OR between both conditions so when both are empty the second part will be true regardless the first part
(tbStartBreak2.Text == "" && tbEndBreak2.Text == "")

Is there a better method to structure this if statement

It just seems a mess to me, my mind tells me there has to be a better way.
I have 6 controls on a web page.
if (printer_make_1.Text != "" && printer_model_1.Text != "" && printer_make_2.Text != "" && printer_model_2.Text != "" && printer_make_3.Text != "" && printer_model_3.Text != "")
{
// Do something
}
What is the best/most efficient way to do this?
You can refactor into a method, if you want to improve the readability or use the same logic elsewhere:
public Boolean AllControlsHaveAValue() {
return (printer_make_1.Text != ""
&& printer_model_1.Text != ""
&& printer_make_2.Text != ""
&& printer_model_2.Text != ""
&& printer_make_3.Text != ""
&& printer_model_3.Text != "");
}
Then just ask:
if (AllControlsHaveAValue()) {
// do something
}
Restructuring starts with your data: avoid printer_make_1, printer_make_2, ...
class PrinterData
{
public string Make { get; set; }
public string Model { get; set; }
}
PrinterData[] printers = new PrinterData[3]; //or use a List<>
printers[0] = new PrinterData { Make = "PH", Model = "1A" };
...
if (printers.All(p => ! (p.Make == "" || p.Model == "")) )
...
if(new[] { printer_make_1, printer_model_1 ...}.All(l => l.Text != string.Empty)
{
//do something
}
You might want to split it up to be more readable:
var labels = new[] { printer_make_1, printer_model_1 ... };
if(labels.All(l => l.Text != string.Empty))
{
//do something
}
I normally put that test into a method and call that to make the if easier to read
private boolean AreAllPrinterFieldsFilled()
{
return (printer_make_1.Text != ""
&& printer_model_1.Text != ""
&& printer_make_2.Text != ""
&& printer_model_2.Text != ""
&& printer_make_3.Text != ""
&& printer_model_3.Text != "");
}
Then in the if:
if (AreAllPrinterFieldsFilled)
{
// Do something
}
There are lots of ways to accomplish this - none of them are elegant. Do what is most readable to you (and those who may come behind you).
I would probably take this approach:
string makeText = String.Concat(printer_make_1.Text, printer_make_2.Text, printer_make_3.Text);
string modelText = String.Concat(printer_model_1.Text, printer_model_2.Text, printer_model_3.Text);
if (makeText.Length != 0 && modelText.Length != 0)
{
// Do something
}
if (!Enumerable.Range(1, 3)
.Any(i => ((TextBox)FindControl("printer_make_" + i)).Text == "" ||
((TextBox)FindControl("printer_model_" + i)).Text == "") {...}
It allows you to later expand the number of printer makes and models, but isn't as strong typed.
private bool CheckAllEmpty(params TextBox[] textBoxes)
{
return textBoxes.All(tb => tb.Text != null);
}
private void Foo()
{
...
if (CheckAllEmpty(tb1, tb2, tb3))
{
mbox("tb1, tb2 and tb3 are all empty");
}
else
{
mbox("tb1, tb2 or tb3 isn't empty");
}
...
}

How to check if a string is built up using only specific characters

I need to check if a string is only built up using 1, 0 and comma. It should also starts with either 0 or 1 and also ends with 0 or 1:
The checking for start and end can be done like this (Or if you think it can be improved peplase let me know!)
if ((text.StartsWith("0") || text.StartsWith("1")) //Starts with 0 or 1
&& (text.EndsWith("0") || text.EndsWith("1")) //Ends with 0 or 1
&& //How to check if it only has 0, 1 and comma? )
{
//Do Something!
}
You can use Regex, try this:
if (new Regex("^[01][01,]*[01]$").Match(text).Success)
{
// do your stuffs
}
public bool CheckMyString(string text)
{
if ((text.StartsWith("0") || text.StartsWith("1"))
&& (text.EndsWith("0") || text.EndsWith("1")))
{
foreach (char c in text)
{
if (c != "1" && c != "0" && c != ",")
{
return false;
}
}
}
else
{
return false;
}
return true;
}
if (Regex.IsMatch("0101,1010", "^[01][01,]*[01]$"))
{
doSomething();
}
you need to add
using System.Text.RegularExpressions;
to the top of your file for this to work.
Use a regular expression like this [01][01,]+?[01]. Im sure there could be better regex patterns to use. But that would work.
if(Regex.IsMatch(mystring, "[01][01,]+?[01]"))
//yes it matches;
This regex pattern will look for a 0 or a 1 and then an optional sequence of 0, 1 or "," and then ending in a 0 or a 1 again.
Is it one way ?
if (value.Trim("01,".ToCharArray()).Length == 0 )
You can try this,
System.Text.RegularExpressions.Regex reg = new System.Text.RegularExpressions.Regex("[01][01,]+?[01]");
if (!reg.IsMatch("3452"))
{
Response.Write("Does Not Match");
}
if (reg.IsMatch("01111,1"))
{
Response.Write("Yes Match!");
}

checking filename

How can i check if filename contains some string? for example if "frody" contains "ro"?
I tried like that:
if (file_name.Contains("ro")== true)
and:
if (file_name.Contains("ro"))
Both are correct. The second is probably more favoured.
E.g., this returns true:
string s = "test-ro.doc";
Console.WriteLine(s.Contains("ro"));
if (s == null || s.Trim().Length == 0)
{
return false
}
else
{
return s.ToLower().Contains("ro");
}

Categories

Resources