0

I have a recursive function that goes like this (I rewrote the problematic part for the purpose of this question):

public class Program
{
    public static void Main()
    {
        var stuff = Foo(new List<int>() { 1, 2, 3, 4, 5 });
        foreach (var item in stuff)
        {
            Console.WriteLine(ListToString(item));
        }
        /*
         * Expected:
         * [2,3,4,5]
         * [1,3,4,5]
         * [1,2,4,5]
         * [1,2,3,5]
         * [1,2,3,4]
         * 
         * Actual:
         * [1,2,3,4,5]
         * [1,2,3,4,5]
         * [1,2,3,4,5]
         * [1,2,3,4,5]
         * [1,2,3,4,5]
         */
        Console.ReadLine();
    }

    public static IEnumerable<IEnumerable<T>> Foo<T>(IEnumerable<T> list)
    {
        var result = Enumerable.Empty<IEnumerable<T>>();
        int count = list.Count();
        if (count % 2 == 0)
        {
            result = result.Append(list);
            return result;
        }

        for (int i = 0; i < count; i++)
        {
            result = result.Concat(Foo(list.Where((_, j) => i != j)));
        }

        return result;
    }

    public static string ListToString<T>(IEnumerable<T> list)
    {
        var res = new StringBuilder();
        res.Append("[");
        res.Append(String.Join(", ", list));
        res.Append("]");
        return res.ToString();
    }
}

I added the expected and actual results to the code above, I hope that makes it clear. In short, the method either prints the whole input list (if it's of even length), or calls itself with a list that got one element removed (=> its length is an even number again).

I really think it's something with the result variable and that it somehow gets overwritten with every call, but I did try renaming it (one path got result, the other worked with result2), and the result stayed the same. Also, the debugger shows that with every iteration in the for loop the result value gets overwritten, and it basically does [[1,3,4,5]].Concat([[1,3,4,5]]) (i = 1 in this example). I would think it'd do [[2,3,4,5]].Concat([[1,3,4,5]]) in this example (first and second iteration of the for loop).

So, there's something I'm not seeing here.

  • 1
    sorry, but I can' t see any recusion. – Serge Jul 24 '21 at 00:43
  • @Serge: `result = result.Concat(Foo(list.Where((_, j) => i != j)));` – Peter Duniho Jul 24 '21 at 00:50
  • 1
    Your sub-sequences capture the loop variable `i`. That means that with each iteration of the loop, _they change_. At the end, the loop variable is set to `6` and so no filtering is done. You need to copy the loop variable value into a local variable declared in the loop, and use _that_. See duplicate. – Peter Duniho Jul 24 '21 at 01:08

0 Answers0