Search code examples
c#castingenumerable

How to AddRange many lists of IEnumerable<IEnumerable<T>> into IEnumerable<List<int>>


I have those functions

    public static IEnumerable<IEnumerable<T>> GetPermutations<T>(IEnumerable<T> items, int count)
    {
        int i = 0;
        foreach (var item in items)
        {
            if (count == 1)
                yield return new T[] { item };
            else
            {
                foreach (var result in GetPermutations(items.Skip(i + 1), count - 1))
                    yield return new T[] { item }.Concat(result);
            }

            ++i;
        }
    }

    public static List<List<int>> GetAllValidCombinations(List<int> items)
    {
        var finalList = new List<List<int>>();
        switch (items.Count)
        {
            case 1:
                finalList.Add(items);
                break;
            case 3:
                finalList.AddRange(GetPermutations(items, 2));
                finalList.AddRange((List<List<int>>)GetPermutations(items, 3));
                break;
        }
        return finalList;
    }

and i want to get an List<List> from GetAllValidCombinations.

In the case 3 of GetAllValidCombinationsin the first line im getting: Error CS1503 Argument 1: cannot convert from 'System.Collections.Generic.IEnumerable<System.Collections.Generic.IEnumerable>' to 'System.Collections.Generic.IEnumerable<System.Collections.Generic.List>'

and if i try the second line im getting error Specified cast is not valid

How i can do this cast in one line?


Solution

  • Sweepers answer is on the money, also you could refactor it a little by only using lists in the inner collection and making it completely generic.

    public static IEnumerable<List<T>> GetPermutations<T>(List<T> items, int count)
    {
       for (var index = 0; index < items.Count; index++)
          if (count == 1)
             yield return new List<T> { items[index] };
          else
             foreach (var result in GetPermutations(items.Skip(index + 1).ToList(), count - 1))
                yield return new List<T> { items[index] }
                   .Concat(result)
                   .ToList();
    }
    
    public static IEnumerable<List<T>> GetAllValidCombinations<T>(List<T> items)
    {
       if (items.Count == 1)
           return new List<List<T>> {items};
    
       if (items.Count == 3)
          return GetPermutations(items, 2)
             .Concat(GetPermutations(items, 3));
    
       return Enumerable.Empty<List<T>>();
    }
    

    Usage

    var results = GetAllValidCombinations(new List<int>() {1, 2, 3});
    
    foreach (var result in results)
       Console.WriteLine(string.Join(",",result));
    

    Output

    1,2
    1,3
    2,3
    1,2,3
    

    Full Demo Here