I have the following block of code:
if (x > 5)
{
if (!DateTime.TryParse(y, out z))
break;
if (w.CompareTo(z) == -1)
break;
}
Where x is an integer, y is a string, z and w are DateTime variables.
The reason for the break; is that whole block resides within a loop.
Is there any way this could be simplified to make it easier to read?
You don't need multilpe if blocks to execute the code because you are only doing one of two things, executing the loop or not executing the loop (one if and one else). As shown here you can use a single boolean expression to represent whether or not you should skip that loop iteration or not.
(x > 5) && (!DateTime.TryParse(y, out z) || w.CompareTo(z) == -1)
Having said that, including a complex condition like this inside of a loop can hamper readability. Personally, I would simply extract this condition out into a method so that the loop looked something like this:
while(!done) // or whatever the while loop condition is
{
if(itemIsValid(x, y, w, out z))
{
//the rest of your loop
}
}
//it may make sense for x, y, w, and possibly z to be wrapped in an object, or that already may be the case. Consider modifying as appropriate.
//if any of the variables are instance fields they could also be omitted as parameters
//also don't add z as an out parameter if it's not used outside of this function; I included it because I wasn't sure if it was needed elsewhere
private bool itemIsValid(int x, string y, DateTime w, out DateTime z)
{
return (x > 5)
&& (!DateTime.TryParse(y, out z) || w.CompareTo(z) == -1)
}
This has several advantages. First, it is a way of self-documenting the code without even needing comments. When looking at the loop you can read it as, "while I'm not done, and if the item is valid, do all of this stuff". If you are interested in how validity is defined you look at the method, if not you skip it. You could also rename the method to something more specific, such as "isReservationSlotFree" or whatever this is actually representing.
If your validation logic is complex (this is somewhat complex) it allows you to add comments and explanation without cluttering the more complex loop.
if (x > 5)
{
if(!DateTime.TryParse(y,out z) || w.CompareTo(z) == -1)
break;
}
Since the two conditionals have the same result, they can be combined into one.
if ((x > 5) && (!DateTime.TryParse(y, out z) || w.CompareTo(z) == -1))
break;
'Simplified' does not mean easier to read.
You can make your code easier to read (and more secured in regards of various coding rules) by:
1) always using brackets for if statements and alikes
2) avoid using '!' ( '== false' is much more explicit)
3) use variable names that explicit what those variables are.
4) avoid multiple break statements. Instead, use a flag that is evaluated in the while's condition.
5) if your code is still hard to read: use comments !
More important: use descriptive variable names for w, x, y, z (hopefully these names were just for your example):
You can also use the less than or greater than operators instead of CompareTo.
if (x > 5)
{
bool isValidDate = DateTime.TryParse(y, out z);
if (!isValidDate || z > w)
{
// comment like: stop processing if the current date
// is after the reference date, or if there was a parsing error
break;
}
}
Here is one more version.
var Break = x > 5 ? ((!DateTime.TryParse(y, out z) || w.CompareTo(z) == -1) ? true : false) : false;
Short but hampers the readability.
if ( x > 5 ){
if (!DateTime.TryParse(y, out z) || w.CompareTo(z) == -1) break;
}
Related
I needed to implement a recursive method that checks whether an input is a palindrome or not. I was able to do this in one line and it works, but I'm not sure about how readable this is. I also keep getting a message "Simplify conditional ternary expression" but I'm not sure how
this is my code:
private static bool checkIfPalindrome(string i_InputToCheck, int i_StartIndex, int i_EndIndex)
{
return (i_StartIndex >= i_EndIndex) ? true : checkIfPalindrome(i_InputToCheck, i_StartIndex + 1, i_EndIndex - 1) && (i_InputToCheck[i_StartIndex] == i_InputToCheck[i_EndIndex]);
}
how readable this is
First off, naming convention: Get rid of unnecessary/uninformative parts of identifiers. For example, parameters do not need to start with i_ (presumably to denote “input”?). There’s no information conveyed here, and it adds noise. This has a huge impact on readability.
The logic itself can also be decluttered. The warning you’re getting gives you a hint that the condition can be simplified — this is always the case when your conditionals contain boolean literals.
More than anything, however, readability would benefit from breaking the expression up over multiple lines.
I would also swap the two secondary conditions, so that you first test the current characters, and then recurse further (only if the two currently tested characters are equal!):
private static bool IsPalindrome(string input, int start, int end) {
return (start >= end) ||
input[start] == input[end] &&
IsPalindrome(input, start + 1, end - 1);
}
This code relies on the correct precedence of && over ||. Some peope prefer making this operator precedence explicit by using more parentheses:
private static bool IsPalindrome(string input, int start, int end) {
return (start >= end) ||
(
input[start] == input[end] &&
IsPalindrome(input, start + 1, end - 1)
);
}
return i_StartIndex >= i_EndIndex || checkIfPalindrome(i_InputToCheck, i_StartIndex + 1, i_EndIndex - 1) && i_InputToCheck[i_StartIndex] == i_InputToCheck[i_EndIndex];
The simplification being prompted is because you're testing a boolean expression and then unnecessarily checking and returning it...
if (expression == true) is equivalent to if (expression) and
return expression ? true : false to return expression.
It is certainly not easy on the eye but I assume this is for a school exercise?
I have a class,
public class NullsAreLast : IComparer<int?>
{
public int Compare (int? x, int? y)
{
if(y == null)
return -1;
else if(x == null)
return 1;
else
return (int)x - (int)y;
}
}
which is self-explanatory on how it is supposed to work.
Whenever I run
arr.OrderBy(i => i, new NullsAreLast())
with at least two null values in arr it runs forever! Any idea why?
Keep in mind that a sorting algorithm may compare the same two values several times over the process of ordering the whole sequence. Because of this, it's very important to be aware of all three possible results: less than, greater than, and equal.
This is (mostly) fine for your integer comparison at the end (the subtraction operation). There are some weird/rare edge cases when working with floating point numbers instead of integers, and calling .CompareTo() is the preferred practice anyway, but subtraction is usually good enough in this case. However, the null checks here are a real problem.
Think about what happens as a list is nearly finished sorting. You have two null values that have both made their way to the front of the list; the algorithm just needs to verify they are in the correct position. Because both x and y are null, your function should return 0. They are equivalent (for this purpose, at least). Instead, the code always returns -1. The y value will always be less than then x value, and so the algorithm will always believe it still needs to swap them. It swaps, and tries to do the same thing again. And again. And again. And again. It can never finish.
Try this instead:
public class NullsAreLast : IComparer<int?>
{
public int Compare (int? x, int? y)
{
if(!y.HasValue)
{
if (!x.HasValue) return 0;
return -1;
}
if(!x.HasValue) return 1;
return x.Value.CompareTo(y.Value);
}
}
The minus operation at the end of your Compare method isn't appropriate for comparison. You need to handle exactly three possibilities - x is bigger, y is bigger, or they are the same.
MSDN
Compares two objects and returns a value indicating whether one is
less than, equal to, or greater than the other.
With this code, suppose X was 1000 and Y was 15. Your result would be 985, which doesn't make sense here.
Given your code and method name, I'm going to guess what you meant is this:
public class NullsAreLast : IComparer<int?>
{
public int Compare (int? x, int? y)
{
if(y == null)
return -1;
else if(x == null)
return 1;
else{
int diff = x - y;
if (diff == 0) return 0; //same
if (diff < 0) return 1; //y was bigger
if (diff > 0) return -1; //x was bigger
}
}
}
You could even smash it into a horrible one-liner:
return (y==null?-1:(x==null?1:(x-y==0?0:(x-y<0?1:-1))));
I have 3 booleans on my code (C#) and an int32 property that depends on what booleans are true and false.
Whats the best way to accomplish this in another way than if statements like:
if(a && b && !c)
d = 1;
if(a && !b && !c)
d = 2;
//etc.. ect...
EDIT: The 3 booleans must have every combination possible to set the int32 value.
EDIT 2: The value of "d" can be the same for two different boolean comparations.
It is better to capture the intent of the operation instead of explicitly check the boolean values.
For example:
public void Check()
{
if (HasOrdered())
{
// do logic
}
}
private bool HasOrdered()
{
return a && !b && !c;
}
private bool HasBooked()
{
return a && b && !c;
}
You could use a Karnaugh map to reduce your equations and have fewer ifs.
https://en.wikipedia.org/wiki/Karnaugh_map
I think what your doing now is perfectly fine and any other solutions would be down to preference.
My preference, where it applies would be to separate the checks out if possible.
if (!a)
return;
if (!b)
return;
if (!c)
return;
This would be useful in the event that you need to check certain prereqs before issuing a function, like if the user has logged in, if a parameter exists and is in the right context, along with other items.
Like i said this might not apply but i just wanted to voice my opinion
You could do the lookup table hint given by #Adriano, assuming you have lookup_table filled with values for index [0..8):
var index = new [] { a,b,c }.Aggregate(0, (a,i) => return 2*a + (i?1:0));
int d = lookup_table[index];
Edit The EDIT of the question made this irrelevant: What does d mean?
If it's the count of false values (possible from the sample code), make it
int d = new [] { a,b,c }.Count(b => !b);
I don't see anything wrong with how you're doing it, but if the output is the same for multiple conditions you may be able to simplify if by creating a truth table and simplifying the conditions.
For example, if d should be 0 anytime a is false you could simplify to:
if(a)
if(b && !c)
d = 1;
if(!b && !c)
d = 2;
...
else
d = 0;
Or if there is some mathematical pattern (e.g. a, b, and c represent the three digits of a binary number) then you could do bit arithmetic.
If, however, you have 8 distinct outcomes (one for each combination of a, b, and c) then your method is fine.
say I have an if statement as such
if(condition1 || condition2 || condition3)
{
//do something
}
Is it possible to find out which of the 3 conditions was true when we enter the loop?
Yes, you can check each one individually with something like:
if(condition1 || condition2 || condition3) {
if (condition1) { doSomethingOne(); }
if (condition2) { doSomethingTwo(); }
if (condition3) { doSomethingThree(); }
doSomethingCommon();
}
assuming of course that the conditions aren't likely to change in the interim (such as with threading, interrupts or memory-mapped I/O, for example).
No. You'll have to do something like:
if(condition1 || condition2 || condition3)
{
if (condition1) {
}
if (condition2) {
}
if (condition3) {
}
//do something
}
It is possible to find out which of the conditions was true by querying each of them using another if, effectively rendering the first if useless.
A simple method.
if(condition1 || condition2 || condition3)
{
if(condition1){
//do something
}
if(condition2){
//do something
}
if(condition3){
//do something
}
}
Or if you know that only one of the conditions is going to be true, consider using a switch.
Before you call the if statement, you can call:
System.out.println(condition1);
System.out.println(condition2);
System.out.println(condition3);
to find out which of the conditions was true.
If you would like to make the program behave differently according to the condition you will need to put that code in a separate if statement.
No. However you can achieve by:
i. Using seperate if else within the 3 or conditions
or
ii. break the three or conditions in separate pairs to find out matching value
You have the short circuit operators. || and &&.
So say for instance you have the condition,
if( x && y || z)
If x && y doesnt evaluate to true, then y and z are never compared. However if X and Y are true, then it will test y or z. In this case your true value comes from the fact that x and y is true, and y or z is true.
Consider the following code:
// this method should add numbers, the requirements are:
// x >= 3 and y <= 5
int add(int x, int y)
{
if(x < 3) throw new ...;
if(y > 5) throw new ...;
}
It's absolutely traditional approach, but in case you pass invalid values for both x and y, you'll only get an exception for x. Why x and not y? Just because you first check x and only then y. Why? That's basically the main question.
In the code above, there's absolutely no sense in checking x before y or y before x. Just because the idea of execution flow in a single thread, some statements are executed before others.
I'm thinking about implementing a mechanism for working with parallel exceptions. The idea is, if there are 2 statements that can be executed simultaneously (execution order doesn't matter) and both of them throw exceptions, I'd like to be able to handle all these exception. The pseudo-code is like following:
// this method should add numbers, the requirements are:
// x >= 3 and y <= 5
int add(int x, int y)
{
parallel
{
if(x < 3) throw new ...;
if(y > 5) throw new ...;
} // point A
return x + y;
}
Somewhere at point A the cumulative exception is thrown. Have you ever seen this approach before, or may be even implemented something of that kind? The main goal here is that if you have a complicated operation, that uses a number of another operation, and the "topmost" operation fails for some reason, you're able to get full diagnostics for what was wrong: not a single error (or a number of nested errors), but a tree of errors.
The questions are:
What do you think?
Have you seen it before?
Have you tried implementing something similar?
Perhaps use an AggregateException?
You seem to want to enforce a set of business rules.
One approach is to create a collection of broken rules and add specific broken rules (e.g. input too short, input must be alphanumeric) as separate elements of that collection, then throw a BrokenRulesException that includes the collection of broken rules as a parameter.
That allows the caller to fully understand what's wrong with the input without changing any language semantics.
Whats wrong with:
int add(int x, int y)
{
if(x < 3 || y > 5)
throw new Error("Incorrect Parameter, x must be >= 3 and y must be <= 5");
}
I think that this would be extraordinarily difficult without implementing something called a continuation -- the ability to return the current state of a function for delayed execution.
Basically, the problem is that instead of an exception (or, rather, a thrown... thing as you do not always have to throw an Exception object in all languages) being a message that a point which cannot be handled has been reached, it would have to return both that and the ability to force continuation past that point anyway. (Thus, you would need continuations)
Additionally, at least on the lower level, this would force the language to always throw an object in those cases. Throwing an int, on the other hand, is occasionally useful.
All of that said, there is nothing stopping you from, say, implementing a macro which works similar to how you've described.
// this method should add numbers, the requirements are:
// x >= 3 and y <= 5
int add(int x, int y)
{
if(x < 3 && y > 5) throw new ...;
if(x < 3) throw new ...;
if(y > 5) throw new ...;
}
Can't this be fairly easily done, without the need for AggregateExceptions or similar:
string ErrorMessage="";
if(x<3) ErrorMessage += "x must be >=3\n";
if(y>5) ErrorMessage += "y must be <=5\n";
if(ErrorMessage!="") throw new Exception(ErrorMessage);
if a string is too simple, it's easy to do something similar with a more complex object type.