C # using LINQ to restrict recursive list

I am trying to figure out how to use LINQ to restrict a recursive call.

My intention with the following code is to execute a list of numbers ( num ) and for each number read / print recursively to a given number ( 6 ).

The sequence in newnum that I am trying to get is: 3 4 5 1 2 3 4 5 5 2 3 4 5

but naturally I came across an infinite loop. The .Where predicate .Where not stop the loop as I thought, and probably my base case is off. Any insight on how to properly install this? Thanks.

 var num = new[] {3, 1, 8, 5, 2}; Func<int, int> writeString = delegate(int count) { Func<int, int> recursiveWrite = null; recursiveWrite = n => { Console.WriteLine("string " + n); recursiveWrite(n+1); return n; }; return recursiveWrite(count); }; var newnum = num.Where(n => writeString(n) < 6); // is this possible? newnum.ToList().ForEach( w => Console.WriteLine(w)); 

I noticed that a similar stop pattern is found in the following code example .Where will only include factorials less than 7, what am I missing?

 var numbers = new[] { 5,1,3,7,2,6,4}; Func<int, int> factorial = delegate(int num) { Func<int, int> locFactorial = null; locFactorial = n => n == 1 ? 1 : n * locFactorial(n - 1); return locFactorial(num); }; var smallnums = numbers.Where(n => factorial(n) < 7); 
+4
source share
4 answers

The answer is that you have no base code. Once your recursive function is executed, it cannot be stopped - LINQ does not execute any magicians that can modify the internal logic of another function.

In the example, you are missing this key bit of code that will stop recursion - the base case:

 locFactorial = n => n == 1 ? 1 : n * locFactorial(n - 1); 

The ternary operator checks if there is n==1 - if it is, it returns 1 . This is a basic case that is not in your function.

It is not possible to provide the base code of your function only through LINQ. You need to build this in a recursive function.

In addition, you return the wrong type from your recursive function if you want to return a list of numbers from one number: this is a fundamentally different case from the Factorial function, which returns a single number with one number.

Here is a function that does what you need without using recursion:

 void Main() { var numbers = new[] {3, 1, 8, 5, 2}; numbers.SelectMany(x => GetIncreasing(x).TakeWhile(y => y < 6)); } IEnumerable<int> GetIncreasing(int x) { while (true) yield return x++; } 
+4
source

You can simply stick with generating sequences that fit your requirements, for example:

 var num = new[] { 3, 1, 8, 5, 2 }; var limit = 6; var query = from n in num where n < limit // sanity check from pn in Enumerable.Range(n, limit - n) select pn; 

Decent performance and clean code

+2
source

The difference with factorial sampling is the placement of the final condition. This is what you should do:

 recursiveWrite = n => { Console.WriteLine("string " + n); if (n < 6) recursiveWrite(n+1); return n; }; 
+1
source

Not quite sure what you are trying to achieve, but I hope this helps. You need a stop condition in your recursive lambda (like n == 1 in factorial). With nested functions, you can enter this limit โ€œdynamicallyโ€.

 class Program { static void Main(string[] args) { var num = new[] { 3, 1, 8, 5, 2 }; Func<int, Func<int, IEnumerable<int>>> writeString = delegate(int maxcount) { Func<int, IEnumerable<int>> recursiveWrite = null; recursiveWrite = (n) => { if (n < maxcount) { Console.WriteLine("string " + n); var rec = recursiveWrite(n + 1); return new List<int>(){n}.Concat(rec); } return new List<int>(); }; return recursiveWrite; }; var newnum = num.SelectMany(n => writeString(6)(n)); // is this possible? newnum.ToList().ForEach(w => Console.WriteLine(w)); Console.ReadLine(); } } 
+1
source

Source: https://habr.com/ru/post/1469188/


All Articles