0

This is more like an exercise. I have several conditions that affect 2 nested for clauses:

for(...)//1st { for(...)//2nd { ... } } 

and since there are various possibilities (each one for a condition) respectively the for1 and for2 can vary.

For example the first for can be

for (int row = 0; row < numRows; row++) 

or

for (int row = numRows - 1; row >= 0; row--) 

so not only changes thes start-end but also the increase/decrease (++ or --)

So i thought that if it was possible to "encapsulate" the for cycle it would have been easy.

Something like (pseudocode)

if(condition1) for1=... else for1=... if(condition2) for2=... else for2=... for1 { for2 { ... } } 

--ADD-- The code itself is pretty simple.

for (int row = numRows - 1; row >= 0; row--) { ... for (int column = 0; column < numColumns; column++) { ... } } 

but if I have the option FlipVertical the first for becomes

for (int row = 0; row < numRows; row++) 

and if I have the option FlipHorizontal the second for becomes

for (int column = numColumns-1; column >=0; column--) 

Again this is not complicated at all. I just wanted to have hints for solving it in a smart, simple and compact way.

And yes I do need the indexes row and column

Thanks

5
  • Do you actually need the index? If not you could use foreach and Enumerable.Reverse. If you do need the index I would be careful to not make things more difficult to read and understand. Commented Oct 22 at 10:01
  • Are we talking about reusability? You could encapsulate for to run inside method of some other class, constructed with all required parameters. It's somewhat common to create static helper methods (often generic) accepting delegate (in your case body of inner for) to run it in the loop with different parameters. Even better is to create extension method, but you need a specific type, e.g. IEnumerable<Item>. Be more specific for a better answer. Also consider codereview, maybe your approach is far from ideal (e.g. can be replaced with a linq). Commented Oct 22 at 10:13
  • Can you please add some more code? A minimal example would be great. Commented Oct 22 at 11:03
  • Thanks guys I have added my real code. Hope it helps to understand that better Commented Oct 22 at 11:52
  • "For" can be coded as a "while"; and while can be powered by any type of (inline) "function" delegate; that can refer to local variables declared earlier and/or instance properties. Commented Oct 23 at 22:47

4 Answers 4

1

If you want to “encapsulate” it Create a tiny helper that returns (start, end, step):

Sign up to request clarification or add additional context in comments.

2 Comments

ah ok so the step can be positive or negative. I hadn't thought about that. Any other solutions?
I am not sure but You can loop forward always and map indices like row = flipV ? r : numRows - 1 - r; and col = flipH ? numCols - 1 - c : c;. Or use a helper make_loop(n, forward) that returns (start, end, step) and loop with for(i=start; i!=end; i+=step)
1

Because you use a for loop, I assume that you need the index. You could write a class that represents a nested for loop:

public class NestedForLoop { public ForLoopHead Outer {get; set; } public ForLoopHead Inner {get; set; } public Action<int,int> Body {get; set; } public void Execute() { for(int i = Outer.StartIndex; Outer.BreakCondition(i); i = Outer.StepAction(i)) { for(int j = Inner.StartIndex; Inner.BreakCondition(j); j = Inner.StepAction(j)) { Body(i,j); } } } } public class ForLoopHead { public int StartIndex {get;set;} public Func<int,bool> BreakCondition {get;set;} public Func<int,int> StepAction {get;set;} } 

The usage could be:

ForLoopHead for1, for2; if(condition1) for1= new ForLoopHead { StartIndex = 0, BreakCondition = x => x < numRows, StepAction =x => x + 1 }; else for1= new ForLoopHead { StartIndex = numRows, BreakCondition =x => x > 0, StepAction = x => x - 1 }; if(condition2) for2= new ForLoopHead { StartIndex = 0, x => BreakCondition = x < numRows, StepAction = x => x + 1 }; else for2= new ForLoopHead { StartIndex = numRows, BreakCondition =x => x > 0, StepAction = x => x - 1 }; var nestedLoop = new NestedLoop { Outer = for1, Inner = for2, Body = (x,y) => Console.WriteLine($"x = {x}, y = {y}") }; nestedLoop.Execute(); 

Online-demo: https://dotnetfiddle.net/9nJS6U

3 Comments

IMHO it should have been a list all "ForLoopHeads" and the outer / inner should be determined by the order it gets added to the list, but it already feels like as it is totally overengineered for a nested for loop
I was also thinking about that, but the lambda expression for the body must have a fixed amount of arguments. Hence I thought that having a flexible amound of loop heads does not improve the code so much.
a strong competitor for github.com/jongeorge1/FizzBuzzEnterpriseEdition-CSharp/tree/…. bonus point for multiple lambdas (very 'fun' to debug)
1

Without seeing the full code it's a bit hard to tell what would be the best approach here.

One I would possibly give a chance is leveraging the magic of yield return and that GetEnumerator returns "fresh one" every time it is called (kind of mimicking a very limited version of generators from other languages like Python).

Small demo:

int numRows = 3; int numColumns = 2; var firstFor = true // to play with ? Generator(0, 1, i => i < numRows) : Generator(numRows - 1, -1, i => i >= 0); var secondFor = Generator(0, 1, i => i < numColumns); foreach (var row in firstFor) foreach (var column in secondFor) { Console.WriteLine($"{row} - {column}"); } // instead of condition you can create an overload // accepting just the "end" number in some cases IEnumerable<int> Generator(int start, int incr, Func<int, bool> condition) { for (int j = start; condition(j); j += incr) { yield return j; } } 

Based on the complexity of the logic you can make separate methods for your for1/for2 methods or reuse the Generate.

Also note that .NET 10 introduces Enumerable.Sequence<T>(T start, T endInclusive, T step) where T : System.Numerics.INumber<T> which can be used instead of Generate method.

Demo @sharplab.io

Comments

0

How about using a working variable like the following?

for (int wrow = numRows - 1; wrow >= 0; wrow--) { var row = FlipVertical ? numRows - 1 - wrow : wrow; for (int wcolumn = 0; wcolumn < numColumns; wcolumn++) { var column = FlipHorizontal ? numColumns - 1 - wcolumn : wcolumn; Console.WriteLine($"{row} , {column}"); } } 

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.