Home > Software design >  LINQ - Flatten a generic dictionary of lists
LINQ - Flatten a generic dictionary of lists

Time:07-09

Following this answer to somebody else's question, I am trying to make a method which will do this for a dictionary of any type.

So far I have come up with the following function, but I am getting a

type arguments for method cannot be inferred

on the SelectMany clause.

public List<T> FlattenDictionary<T>(Dictionary<object, T> dictionary)
{
    var list = dictionary.Values              // To get just the List<string>s
             .SelectMany(x => x)  // Flatten
             .ToList();           // Listify

    return list;
}

Following the answer from @Ctznkane525, I have come up with the following:

public List<T> FlattenListDictionary<I, T>(Dictionary<I, T> dictionary) where T : IEnumerable<T>
{
    var list = dictionary.Values              // To get just the List<string>s
             .SelectMany(x => x)  // Flatten
             .ToList();           // Listify

    return (List <T>) list;
}

This now compiles without any errors but I still can't use the function because I get an error. Take the following example:

var dictionary = new Dictionary<int, List<string>>();
var list_1 = new List<string>();
list_1.Add("hello");
list_1.Add("good morning");
list_1.Add("hi");

var list_2 = new List<string>();
list_2.Add("cat");
list_2.Add("dog");
list_2.Add("mouse");

dictionary[10] = list_1;
dictionary[320] = list_2;

var list = (List<string>) FlattenListDictionary(dictionary);

With our without the cast I get the following error:

The type 'System.Collections.Generic.List' cannot be used as a type parameter 'T' in the generic type or method 'FlattenListDictionary<I,T>(Dictionary<I,T>). There is no implicit reference conversion from System.Collections.Generic.List to System.Collections.Generic.IEnumerable<System.Collection.Generic.List>'.

I also tried changing

where T : IEnumerable<T>

to

where T : List<T>

but that didn't help.

CodePudding user response:

In the other example, the value type of the dictionary is a list. You just need a similar constraint.

where T : IEnumerable - should do that.

public List<T> FlattenDictionary<T>(Dictionary<object, T> dictionary) where T : IEnumerable<T>
{
    var list = dictionary.Values              // To get just the List<string>s
                 .SelectMany(x => x)  // Flatten
                 .ToList();

    return list;

}

CodePudding user response:

Thinking you can achieve, without specifying the constraint.

public static List<T> FlattenListDictionary<I, T>(Dictionary<I, List<T>> dictionary)
{
    var list = dictionary.Values              // To get just the List<string>s
        .SelectMany(x => x)  // Flatten
        .ToList();           // Listify
        
    return list;
}

Calling method:

FlattenListDictionary(dictionary);

Sample NET Fiddle

  • Related