Search code examples
c#linq.net-6.0

Flatten a sequence of sequences into a single sequence (List<string> from List<Object> contains that List<string>)


I'm trying to extract some Lists of strings into a single List. First I have this class

public class Client
{
  public string Name { get; set; }

  public List<string> ApiScopes { get; set; }
}

Thus I'm getting my response as a List<Client> and my intention is to take all Client's Scopes into a single List without Looping I've tried this by LINQ:

 var x = clients.Select(c=> c.AllowedScopes.Select(x => x).ToList()).ToList();

this returns a List<List<string>>, and I just want to get all this into one Distinct list of strings.


Solution

  • It sounds like you want SelectMany (which flattens a sequence of sequences into a single sequence), with Distinct as well if you need a list with each scope only appearing once even if it's present for multiple clients:

    var scopes = clients.SelectMany(c => c.ApiScopes).Distinct().ToList();
    

    This assumes that Client.ApiScopes is never null. If it might be null, you need a little bit more work:

    var scopes = clients
        .SelectMany(c => ((IEnumerable<string>) c.ApiScopes) ?? Enumerable.Empty<string>())
        .Distinct()
        .ToList();