I am trying to make two loops into one. This Loop should go through the array from the beginning to the end and otherwise. However my increment is not correct. Can anyone help? Thank you in advance.
for (int i = ((asc == true) ? 0 : calendar.Length - 1);
((asc == true) ? i < calendar.Length : i > 0);
(asc==true) ? i++ : i--)
Personally, I find that very hard to read, as well as invalid (it won't compile) - because you're trying to use the conditional operator as a statement expression, when it's not. Personally, I'd write something like:
for (int i = 0; i < calendar.Length; i++)
{
int index = asc ? i : calendar.Length - 1 - i;
// Now use index...
}
Making three different aspects all conditional feels like a nasty way to go.
Look at the C# reference of "for": http://msdn.microsoft.com/en-us/library/ch45axte.aspx
Specifically:
The iterator section defines what happens after each iteration of the body of the loop. The iterator section contains zero or more of the following statement expressions, separated by commas:
assignment statement
invocation of a method
prefix or postfix increment expression, such as ++i or i++
prefix or postfix decrement expression, such as --i or i--
creation of an object by using new
await expression
The expression: "(asc==true) ? i++ : i--" is none of these things.
Therefore, you'd want the assignment: i += (asc ? 1 : -1)
for (int i = ((asc) ? 0 : calendar.Length - 1);
((asc) ? i < calendar.Length : i >= 0);
i += (asc) ? 1 : -1)
Incidentally, as pointed out in comment, you'll probably want to look at index 0 in the condition, so your condition statement in the "descending" case should be i >= 0 (reflected in the code).
Jon offered a good option, but if principle:
for (int i = (asc ? 0 : calendar.Length - 1);
asc ? i < calendar.Length : i >= 0;
i += asc?1:-1)
{
//body
}
That for loop is... odd. It is also very hard to read. In the spirit of "better ways to do this", I would suggest just using Reverse:
IEnumerable<Day> collection = asc ? calendar : calendar.Reverse();
for (int i = 0; i < calendar.Length; i++)
{
collection.ElemantAt(i);// This is the current element
}
//Or better, you are getting everything anyways:
foreach (Day day in collection)
{
}
Related
I been searching for some information about if statements with multiple conditions but haven't found something that corresponds to myquestion.
I was wondering if you could write:
int n = 3
if (3 < n < 20)
{
//do something..
}
rather than doing:
if (n > 3 && n < 20)
{
//do something..
}
The first statement doesn't work for me which i think it should, because it's plain simple.
Maybe someone can give me the correct syntax for doing so or maybe it's just impossible at all and i just have to go with the AND.
To explain why it's invalid:
if (3 < n < 20)
Could be rewritten as:
if ((3 < n) < 20)
Now 3 < n's outcome would be a bool.
So basically you'll get:
if (true/false < 20)
Which is not valid in C#.
Stefan's answer explains why it's impossible.
But here is a workaround, if you don't want to write that pesky && explicit conditions every time - you can create an extension method:
public static class IComparableExtensions
{
public static bool Between<T>(this T self, T low, T high) where T : IComparable
{
return self.CompareTo(low) > 0 && self.CompareTo(high) < 0;
}
}
And use it like this:
int n = 5;
if(n.Between(3, 20))
{
// do your stuff here
}
Please note, however, that this might be confusing - since Between doesn't specify if the compare is inclusive, exclusive, or inclusive in only one direction - so if you compare, say, 20.Between(10, 20) - should it return true or false?
A better approach would require adding another variable to the method, to indicate that:
[Flags]
public enum CompareMode
{
Exclusive = 0,
IncludeLow = 1,
IncludeHigh = 2,
Inclusive = IncludeLow | IncludeHigh
}
public static class IComparableExtensions
{
public static bool Between<T>(this T self, T low, T high, CompareMode mode) where T : IComparable
{
var compareLow = (mode & CompareMode.IncludeLow) == CompareMode.IncludeLow ? 0 : 1;
var compareHigh = (mode & CompareMode.IncludeHigh) == CompareMode.IncludeHigh ? 0 : -1;
return self.CompareTo(low) >= compareLow && self.CompareTo(high) <= compareHigh;
}
}
Now you use it like this:
if(n.Between(3, 20, CompareMode.Exclusive))
{
// do your stuff here
}
You can see a live demo on rextester.
This way, another person reading this code (or even you, 6 months from now) will know immediately, without having to look inside the Between extension method, if between is inclusive, exclusive, or whatever.
Generally it is not possible what you want to do.
but in your logic if you want to perform single liner logic you can use ternary operator.
for eg. you need to assign value of n to variblae result else it should be 0 as default.
int result = n > 3 ? (n < 20 ? n : 0) : 0
it is equivalent to
int result = 0;
if (n > 3 && n < 20)
{
result = n;
}
Not sure what I am doing wrong here. I am new to C# and am trying to convert VB.Net code from an online tutorial. I can't get this For loop to iterate:
if (Screens.Count > 0)
{
for (int i = Screens.Count - 1; i == 0; --i)
{
if (Screens[i].GrabFocus==true)
{
Screens[i].Focused = true;
DebugScreen.FocusScreen = "Focused Screen: " + Screens[i].Name;
break;
}
}
}
There are 2 screens in the list. The second screen (Screens[1]) has GrabFocus set to true. During debugging, execution jumps from line 3 (for ...) right to the last closing brace. The nested "If" statement never executes. Also, I think the break statement is wrong because I am actually trying to end the "For" loop.
You haven't written correctly your for loop. You should replace it with the following:
for (int i = Screens.Count - 1; i >=0; --i)
You start from the value Screens.Count - 1 and you decrease by 1 the i in each step, until i becomes equal to zero. Then you stop.
Generally speaking, the correct syntax is the following:
for (initializer; condition; iterator)
body
The initializer section sets the initial conditions. The statements in this section run only once, before you enter the loop. The section can contain only one of the following two options.
The condition section contains a boolean expression that’s evaluated to determine whether the loop should exit or should run again.
The iterator section defines what happens after each iteration of the body of the loop. The iterator section contains zero or more of the following statement expressions, separated by commas
The body of the loop consists of a statement, an empty statement, or a block of statements, which you create by enclosing zero or more statements in braces.
For more information about this, please have a look here.
What's the problem in your case?
The second bullet. The condition, i==0 is false by the begin. Hence the loop will not be executed at all.
i == 0 should be i >= 0
i.e.
for (int i = Screens.Count - 1; i >= 0; --i)
i == 0 should be replaced with i >= 0
for (int i = Screens.Count - 1; i >=0; --i)
Your for loop is not correct. Here's is the code
if (Screens.Count > 0)
{
for (int i = Screens.Count - 1; i >= 0; --i)
{
if (Screens[i].GrabFocus==true)
{
Screens[i].Focused = true;
DebugScreen.FocusScreen = "Focused Screen: " + Screens[i].Name;
break;
}
}
}
At some point I wanted to randomize if an array would be inverted or not while creating it.
One of the first things I figured was this:
bool reverse = Random.value > 0.5f;
for (
int i = reverse ? steps - 1 : 0;
reverse ? i >= 0 : i < steps;
i += reverse ? -1 : +1
) {
rotateScript.angles.Add(angleRange[0] + stepAdder * i);
}
Later I realized despite taking more lines, two for loops inside an if/else would be more readable.
But the question remained: Would those ternary conditions be executed each iteration, or just once?
Correct, the 2nd and 3rd components of the for statement are evaluated in every iteration.
This:
for( x; y; z ) a;
Is equivalent to:
x;
while( y ) { a; z; }
So y will be evaluated 1 more time than z.
As #Dai pointed out, the second and third statements must be evaluated at the end of each iteration.
This behaviour is detailed in §8.8.3 of the C# language specification. Paraphrased, it says about a
for ( initialiser; condition; iterator; ) { ... }
statement:
A for statement is executed as follows:
If a for-initializer is present, the variable initializers or statement expressions are executed in the order they are written. This step is only performed once.
If a for-condition is present, it is evaluated.
If the for-condition is not present or if the evaluation yields true, control is transferred to the embedded statement. When and if control reaches the end point of the embedded statement, the expressions of the for-iterator, are evaluated in sequence, and then another iteration is performed, starting with evaluation of the for-condition in the step above.
If the for-condition is present and the evaluation yields false, control is transferred to the end point of the for statement.
With your code
for (
int i = reverse ? steps - 1 : 0;
reverse ? i >= 0 : i < steps;
i += reverse ? -1 : +1
) {
rotateScript.angles.Add(angleRange[0] + stepAdder * i);
}
you do have a few options to make the ternary operator at reach iteration unnecessary.
You mentioned using an if/else with two for loops but I suggest that you do not do that because it duplicates code, which hinders its maintainability, and readability.
Option 1: Use a standard for loop:
You can put the logic into the code inside the loop, i.e.
for ( i = 0; i < steps; i += 1 )
{
int multiplier = reverse ? steps - 1 - i: i;
rotateScript.angles.Add(angleRange[0] + stepAdder * multiplier);
}
Option 2: Move the ternary logic out:
Calculate the limit and the increment first, i.e.
int start = reverse ? steps - 1 : 0;
int increment = reverse ? -1 : +1;
int limit = reverse ? -1 : steps;
for ( int i = start; i != limit; i += increment; )
{
rotateScript.angles.Add(angleRange[0] + stepAdder * i);
}
I prefer option 1 as I think most people find straightforward for loops easier to understand.
I'm trying to get away with a slick one liner as I feel it is probably possible.
I'll put my code below and then try to explain a little more what I'm trying to achieve.
for (int p = 0; p < 2; p++)
{
foreach (string player in players[p])
{
if (PlayerSkills[player].streak_count *>* 0) //This line
PlayerSkills[player].streak_count++;
else
PlayerSkills[player].streak_count = 0;
}
}
*(p==0 ? >:<) the comparison operator is chosen depending on p.
Of course what I've written is rubbish. But basically I want to use >0 when p==0, and <0 when p>>0. Is there a nice way to achieve this?
Well, you should use what is most readable, even if it is not as consice. That said...
// Invert the count for all but the first player and check for a positive number
if (PlayerSkills[player].streak_count * (p==0 ? 1 : -1) > 0)
I don't know about slick, but the following and/or combination is one line:
if ((p == 0 && PlayerSkills[player].streak_count > 0)
|| PlayerSkills[player].streak_count < 0)
...
This will only ever do the array index once (due to the p==0 condition occurring first) and so is equivalent to the "ternary" you wrote (albeit a bit more verbose).
p > 0 ? whenGreaterThanZero : whenZeroOrLess ;
E.g.
int p = 1; bool test = p > 0 ? true : false ;
Lets test = True
I have a function with multiple if's (THIS IS NOT THE ACTUAL CODE)
if(n == 1)
m = 1;
if(n == 2)
m = 2;
if(n == 3)
m = 3;
Instead of that I wanted to do make them all into ?: expression :
(n == 1) ? m = 1;
But it says that its expecting a ':'
I am familiar with the ?: expression from C++ where you can simply write:
(n == 1) ? m = 1 : 0;
But 0 doesn't take here. This is a ridiculous question and I couldn't even find an answer in google since it ignores '?:' as a word.
ANSWER : too bad the answer was in the comments. There is no way to "do nothing" in this expression and I should use if-else or switch. thanks.
It looks like you're looking for:
m = (n == 1) ? 1 : 0;
Which you could then cascade to:
m = (n == 1) ? 1 : (n == 2) ? 2 : (n == 3) ? 3 : 0;
An important (to me, anyway), aside:
Why are you asking this? If it's because you think that this form will be more efficient than a series of if statements, or a switch, don't. The C# compiler and the .net JIT compiler are really quite clever and they'll transform your code (hopefully!) into its most optimal form. Write your code so its as understandable by yourself, or the developer who has to maintain it after you as it can be. If the performance you get isn't acceptable, then try changing it around but measure to determine what works best (bearing in mind that newer compilers/.net frameworks could well change what happens).
looking for ternary operator in c# will give you relevant results.
an example usage would be
var m = n == 1 ? 1 : 0
Maybe:
m = (n == 1) ? 1 : (n == 2) ? 2 : (n == 3) ? 3 : m;
or
m = n
Edit:
Simplified:
variable2 = (variable1 == value) ?
variable1 :
variable2;
You want this:
m = (n == 1) ? 1 : 0;
To nest them all it would look like this:
m = (n == 1) ? 1 : (n == 2) ? 2 : (n == 3) ? 3 : 0;
But as you can see, this is really a lot less easy to read and understand. It can help to add extra parenthesis, but I think you're better off using an if-else tree.
m = (n == 1) ? 1 : m
Means
M equals 1 if n == 1, else m
FYI the ? is called the Ternery operator. Find usage on MSDN
Best regards,
You could write:
m = (n==1) ? 1 : m;
But IMO that's harder to read and uglier than the original code.
(n == 1) ? m = 1 : 0;
This isn't allowed because C# doesn't allow arbitrary expressions as a statement. Method calls and assignments are allowed, most other expressions aren't.
A statement is executed for its side-effects, an expression for its value. So it's only natural that the outermost part of a statement has a side effect. ?: never has a side-effect, so it's not allowed as a statement.
Try this :
m = (n == 1) ? 1 : 0;
This is not a problem to be solved with a ternary if/else operator - it is clearly an ideal candidate for a switch statement (and using a switch is likely to be much more efficient than using a sequence of ternary operators)
If you wish to transliterate an if statement into ?:, then it's quite simple:
if ({condition}) {then-code}; else {else-code};
becomes
{condition} ? {then-code} : {else-code};
The only restriction is that the then/else code is a single statement.
The primary benefit of ?: (with modern compilers) is that it can be embedded within a statement to significantly compress the source code - sometimes this can aid readability, and sometimes it just serves to obfuscate the meaning of the code - use it with care.