I am modifying another developer's code and I don't know what the [0] bracket following the string means in this context, can someone explain to me? My first thought is it is referring to the first column of GridView1 but that isn't the correct way to designate a column is it? BTW the string values in the if statement are 7 digit numbers expressed as strings. The first column is the DataKey column.
if (GridView1.SelectedValue.ToString()[0] != '5' && GridView1.SelectedValue.ToString().Substring(0, 2) != "95")
{
LinkButton1.Visible = false;
LinkButton2.Visible = false;
}
else
{
LinkButton1.Visible = true;
LinkButton2.Visible = true;
}
String Accessing Individual Characters
You can use array notation with an index value to acquire read-only
access to individual characters
if (GridView1.SelectedValue.ToString()[0] != '5' && GridView1.SelectedValue.ToString().Substring(0, 2) != "95")
As noted in the comments, both the below will throw if there are not enough characters
GridView1.SelectedValue.ToString()[0]
GridView1.SelectedValue.ToString().Substring(0, 2)
Also as per DRY calling this twice is redundant and also messy
GridView1.SelectedValue.ToString()
When you can
var something = GridView1.SelectedValue.ToString();
Lastly, normally you would check this for sanity sake, Like
if(!string.IsNullOrEmpty(something) && something.Length >= 2)
if (something[0] != '5' && something.Substring(0, 2) != "95")
Anyway, have fun stringing
Related
So I'm doing this years Advent of Code and I'm stuck on the second day, part 2.
You are given inputs which look like this:
"1-3 c: caaasa"
You have to check how many passwords are valid due to the policy like,
in above example:
letter c has to be in position 1 OR 3 in the string caaasa. If
yes, the password is valid.
I've broken down that string to different sections, and now I try to compare a string "znak" which contains that given letter to a letter on position zakresmin and zakresmax in string "passdiv"
Yet, everytime it returns False, so it doesn't add up to the count of passwords.
I tried using Equals() and CompareTo(), but they don't seem to work.
How can I modify my code so it returns proper values?
var iloschasel = 0;
using (StreamReader sr = new StreamReader(#"C:\Users\Wurf\Desktop\text.txt"))
{
string line;
while ((line = sr.ReadLine()) != null)
{
string[] linia = line.Split(" ");
string zakres = linia[0];
string[] zakresy = zakres.Split("-");
int zakresmin = Convert.ToInt32(zakresy[0]);
int zakresmax = Convert.ToInt32(zakresy[1]);
string znak = (linia[1].Replace(":", "")).Trim();
var suma = Regex.Matches(linia[2], znak);
string passdiv = linia[2];
if(passdiv[zakresmin].Equals(znak) || passdiv[zakresmax - 1].Equals(znak))
{
iloschasel += 1;
}
}
}
Console.WriteLine(iloschasel);
As mentioned, when you call Equals on two different types you are playing a game of chance with how the actual types are implemented. In this case you lose. Strings and chars will never have an equivalence or the same reference.
I believe the compiler or resharper would give you a warning alerting you that neither type derive from string and char
However, I was bored enough to give an alternate solution
public static bool IsValid(string input)
{
var match = Regex.Match(input, #"(\d)-(\d) (\S): (.*)");
if(!match.Success)
throw new ArgumentException( $"Invalid format : {input}",nameof(input));
var first = int.Parse(match.Groups[1].Value);
var second = int.Parse(match.Groups[2].Value);
var c = char.Parse(match.Groups[3].Value);
var password = match.Groups[4].Value;
return password[first-1] == c && password[second-1] == c;
}
Test
Console.WriteLine($"Is Valid = {IsValid("1-3 c: caaasa")}");
Console.WriteLine($"Is Valid = {IsValid("1-3 c: cacaasa")}");
Output
Is Valid = False
Is Valid = True
Note : this is not meant to be a complete bullet-proof solution. Just a novel elegant way to solve your problem
Your problem is that you are comparing a string to a char
var match = "c" == 'c';
Will give a compile error because they are different data types
var match = "c".Equals('c');
will let you compile, but will always return false because a char will never equal a string. You have to turn the char into a string or visa versa for the check to work
var match = "c"[0] == 'c';
So in your if statement, if you fix the check to compare strings with strings or chars with chars you should get some positive results. And also fix your indexing issue to decide if you want a 0 based index or a 1 based index with zakresmin and max
Also as a side note, it can be helpful to step through your code line by line in debug mode, to find out which line isn't behaving like you expect it to. In your case debugging would have helped you zero in on the if statement as a starting point to fixing things.
So it turns out (if I understand that correctly) that a compared element of the string passdiv was a char which I tried to compare to znak which was a string. I added ToString() to my code and it works well. Also fixed the range of zakresmin by subtracting 1 so it works properly.
if((passdiv[zakresmin - 1].ToString() == znak && passdiv[zakresmax - 1].ToString() != znak) || (passdiv[zakresmin - 1].ToString() != znak && passdiv[zakresmax - 1].ToString() == znak))
{
iloschasel += 1;
}
I have this piece of code which i simplified from my app. It does what I want but I know its not put in the most efficient way because I'm still having some trouble understanding the && and & operators.
if (AgeInput.Text.Equals(""))
{
Textblock1.Text = "✘";
}
else if (AgeInput.Text.All(Char.IsNumber)){
Textblock1.Text = "✔";
//DO-THIS-A
}
else
{
Textblock1.Text = "✘";
}
I need it to make sure there is no white spaces in the string and to also check so its not empty and finally check if its a number, If it ticks all those requirements it will //DO-THIS-A
Whats the most efficient way to do this?
EDIT:
If somebody knows how to make a XAML textbox numerical only (so no whitespaces) that would be even better (only a single property or don't worry otherwise)
if(!String.IsNullOrEmpty(AgeInput.Text) && AgeInput.Text.All(char.IsNumber))
Textblock1.Text = "✔";
else
Textblock1.Text = "✘";
String.IsNullOrEmpty returns true if the input is as stated: Null or Empty.
We Invert that with the "!", so that it returns true if it isn't empty.
Then we add the && Operator to expand the if condition and ask if the text only contains numbers.
Also look here: For a description of the difference between &, && and |, ||
Not really sure I understand your question, because && and & are for totally different uses.
if (string.IsNullOrWhiteSpace(AgeInput.Text))
{
Textblock1.Text = "✘";
}
else if(Char.IsNumber(AgeInput.Text.All))
{
Textblock1.Text = "✔";
}
The & is a binary operator and && is a logical operator.
I am seeing lots of these in a method in our code:
int num1 = 0;
if (Char.IsDigit(myStr[2]) && Int32.TryParse(myStr[2].ToString(), out num1) == false)
{
valid = false;
}
So are they just making sure the third character us a digit?
The code shown parses the 3rd character only - checking if it is digit, then parsing the string representation of that single character. Instead, just use the numeric value of that character:
if(myStr[2] >= '0' && myStr[2] <= '9') {
num1 = (int)myStr[2] - (int)'0';
} else {
valid = false
}
You can safely skip the IsDigit() check as it's redundant.
TryParse() will fail if it's not a digit.
As it has been pointed out by others, Char.IsDigit() is quicker. If your code is performance sensitive the check makes sense.
If you leave the IsDigit check in place, then you can reduce TryParse to Int32.Parse() as at that point the parsing won't fail.
It looks like the code that you have is doing this for efficiency. Whoever coded this, knows the structure of the string in myStr to sometimes have a non-numeric symbol in the third position. That's why he made this optimization to check the third symbol before paying for the conversion of the character array to string which then gets parsed.
Chances are, this optimization is premature: although making a temporary throw-away string is not free, this optimization would make sense only in situations when you do it a lot in a very tight loop. In other words, you do it only if it shows up near the top in your performance profiler's output.
You can optimize this check to avoid if:
int num1 = 0;
valid &= !Char.IsDigit(myStr[2]) || Int32.TryParse(myStr[2].ToString(), out num1);
I don't believe you need the first part (it could also throw an IndexOutOfRangeException).
So I would probably use:
int num1 = 0;
if (myStr.Length > 2 && Int32.TryParse(myStr[2].ToString(), out num1) == false)
{
valid = false;
}
Char.IsDigit Method (String, Int32)
Indicates whether the character at the specified position in a specified string is categorized as a decimal digit.
Link
Int32.TryParse Method
Converts the string representation of a number to its 32-bit signed integer equivalent. A return value indicates whether the operation succeeded. This member is overloaded.
Link
Edit:
First I wrote that you can skip any of the check but now I am writing that you can not because
if (Char.IsDigit(myStr[2]) && Int32.TryParse(myStr[2].ToString(), out num1) == false)
{ }
Char.IsDigit() will return true if myStr[2] contains any of the Unicode characters listed here but Int.TryParse() will not convert any numbers except for 0-9 (not sure about this, as I have not checked all of them) so it will return false which is you are checking...
The condition you are checking can be understood by the following example:
string x = "AS௭s";
int s = 0;
if (Char.IsDigit(x[2]) && int.TryParse(x[2].ToString(), out s) == false)
{
// even if '௭` is Tamil Digit Seven and 'Char.IsDigit()' will return true but
// int.TryParse() will return false because it can not convert it
// so you are setting valid = false when the myStr contains a valid Unicode Character
// for a digit but It can not be converted to integer by TryParse method...
valid = false;
}
#Marc Gravell♦'s answer is the best solution for checking this condition...
Here's how I'd write it:
int num1 = 0;
try
{
num1 = Int32.Parse(myStr[2].ToString());
}
catch (Exception)
{
valid = false;
}
This does the same thing and is a lot easier to read imho, oh & you can log failed parses inside the catch.
Or you can do:
int num1 = 0;
valid = Int32.TryParse(myStr[2].ToString(), out num1);
I have one logical question. I have collection of employee objects
There are 3 filter criteria conditions which have handle
For e.g. Employee name, Office name, salary.
Now these filter criteria should match like (Employee name AND/OR Office name AND/OR salary)
So here I have to write (2 raise n) -1 if conditions to handle this situation.
Is there any other way we can do this.
For (Employee name AND/OR Office name) condition I m doing following
if (criteria.EmpName != "" && criteria.OfficeName != "")
{
if (emp.EmpName == criteria.EmpName && emp.OfficeName == criteria.OfficeName)
{
bIsMatch = true;
}
}
else
{
if (criteria.EmpName != "" && emp.EmpName == criteria.EmpName)
bIsMatch = true;
else if (criteria.OfficeName != "" && emp.OfficeName == criteria.OfficeName)
bIsMatch = true;
}
Now if have to handle saraly also i have write min 5 conditions.
Is thr other way to do it?
There are lots of ways to do it, but since you didn't specify one specific language and since I don't feel qualified to judge your coding style, here's one that keeps the general form of your code, while demonstrating some better logic:
bool bIsMatch = true;
if (criteria.EmpName != "" && criteria.EmpName != emp.EmpName) {
bIsMatch = false;
} else if (criteria.OfficeName != "" && criteria.OffIceName != emp.OfficeName) {
bIsMatch = false;
} /* Repeat for as many conditions as there are */
if (bIsMatch) {
/* None of the checks above failed */
}
You can pair up your filtering conditions and have a single statement that encodes all the parameters:
if( (criteria.EmpName.equals("") || criteria.EmpName.equals(emp.EmpName))
&& (criteria.OfficeName.equals("") || criteria.OfficeName.equals(emp.OfficeName))
&& (criteria.Salary.equals("") || criteria.Salary.equals(emp.Salary)))
In each of the AND-ed expressions checks first if the filter is empty, if it is that piece will result in true, if it's not, then the check is performed against the corresponding value in emp and is true only when that check is true.
Start out by assuming you have a match and Then apply each criterion one by one.
bIsMatch = true;
if (bIsMatch && criteria.EmpName != "") bIsMatch = emp.EmpName == criteria.EmpName;
if (bIsMatch && criteria.OfficeName != "") bIsMatch = emp.OfficeName == criteria.OfficeName;
// ...
Or, write a helper function that does the matching.
bool IsMatch(String criterion, String value)
{
return criterion == "" || criterion == value;
}
Then you can do everything in one big if statement:
if (IsMatch(criteria.EmpName, emp.EmpName) &&
IsMatch(criteria.OfficeName, emp.OfficeName) &&
...
)
You can check the criteria individually and maintain a count of matches. That way you need only n conditions:
int matches = 0;
if (criteria.EmpName != "" && emp.EmpName == criteria.EmpName)
matches++;
// similar code for other criteria
if (matches >= 2) { // as many matches as required
// succeeded
}
How about this? The idea scales well for more filters, except that the mapping itself is convention based (name - name).
var map = new Dictionary<string, string>
{
{ criteria.EmpName, emp.EmpName },
{ criteria.OfficeName, emp.OfficeName},
{ criteria.ThirdProp, emp.ThirdProp }
};
bIsMatch = dict.All(kvp => string.IsNullOrEmpty(kvp.Key) || kvp.Key == kvp.Value);
I would question the overall design though; there's something that doesn't seem right about it. How would you deal with the Salary field that you mention? Surely, that's not a string? What's the sentinel-value being used in that case?
Make sure you are clear enough about the business logic before writing the code. According to your code, I can see that you want to check if emp and criteria have the same EmployeeName and OfficeName, any of the properties is considered to be the same if it's string.Empty. The code will be quite clear after yourself is clear. Here we go:
public static bool EmptyOrEquals(this string one, string another)
{
return string.IsNullOrEmpty(another) || one.Equals(another);
}
bIsMatch = emp.EmpName.EmptyOrEquals(criteria.EmpName)
&& emp.OfficeName.EmptyOrEquals(criteria.OfficeName);
Test each question individually and use a bit set to encode the combinations of answers.
This results in cleaner code because you only test each criteria once, it's compact yet readable, and yet you can easily plug in code to handle each combination. And it's the fast too. O(n) to test all the criteria and O(1) to find the actual combination.
For a small, fixed number of criteria, you can push bits around manually. For many criteria, or for a solution that scales, use java.util.BitSet
Bit pushing example:
int bits = 0;
if (...criteria 1...) {
bits = 1;
}
if (...criteria 2...) {
bits |= 2;
}
if (...bits 3...) {
bits |= 4;
}
switch (bits) {
case 0: // no criteria matched
;
case 1: // criteria 1 matched
;
case 2: // criteria 2 matched
;
case 3: // criteria 1 AND 2 matched
;
case 4: // criteria 3 matched
;
case 5: // criteria 1 AND 3 matched
;
case 6: // criteria 2 AND 3 matched
;
case 7: // criteria 1 AND 2 AND 3 matched
;
}
You can generalize this solution using java.util.BitSet to manipulate bits for n criteria (useful when n > 64!). To facilitate quick look up, store the hash of each BitSet combination in a map that maps the hash code to a command class.
I want to check if two string are of the same length. I tried the following, but it doesn't work.
string passnew = "1233";
string passcnfrm = "1234";
if((passnew.Length&&passcnfrm.Length)>6 ||(passnew.Length&&passcnfrm.Length)<15)
{
// ...
}
Why does it not work? What do I need to change?
if(passnew.Length == passcnfrm.Length &&
passnew.Length > 6 && passnew.Length < 15)
{
// do stuff
}
You are missing some basic syntax lessons. What you write inside of these brackets are conditions. We have unary operators (operating on one thing), binary operators (two) and one tertiary operator (forget about that one).
You cannot construct something like your "boundary test" with those easily.
A possible way:
(passnew.Length > 6) && (passcnfrm.Length > 6)
But you aren't testing if the length is equal anyway, even if you could use a syntax like that. You seem to want to compare if both are longer than 6 chars and shorter than 15 chars. One at 7 and one at 14 would satisfy both conditions..
if(passnew.Length == passcnfrm.Length &&
(passnew.Length < 15 && passnew.Length > 6))
{
// ...
}
Checks both are same length, and either one is more than 6 and less than 15 characters long.
that would be:
if(passcnfrm.Length.Equals(passnew.Length))
{
//do stuff
}
A probably better way to do it is:
if (( passnew != null && passcnfrm != null )
( passnew == passcnfrm )
&& ( passnew.Length > 6 && passnew.Length < 15 ))
{
// do stuff
}
Hides the length check inside the equality check which you'll probably need, it isn't in your question but the variable names make it pretty clear you're doing a password change function there. I added the null check to make sure the length checks don't throw a NullReferenceException, not needed in the example because you assign both manually, but might save some trouble if you're going to convert this to a method later on.
You can use like this:
if (s.Contains(s1[i]))
or:
boolean equalsIgnoreCase(String anotherString);
or use this method:
public static int occurrence(string [] a, string a2)
{
int occ = 0;
for (int i = 0; i < a.Length;i++ )
{
if(a[i].Equals(a2))
{
occ++;
}
}
return occ;
}