Ada
Ada

Reputation: 624

How to get list that is the distinct select of other lists (LINQ)?

Sorry about the question, I couldn't build the sentence. Here is what I have,

class Brand{
    int ModelId;
    string name;
}

class Gallery{

    IList<Brand> brands;
    ...
    public BrandList{
        get{ return brands; }
    }
}

I have a list of Gallery. Like this,

IList<Gallery> galleries;

and each Gallery in galleries have many Brands in it. For example, galleries have 6 Gallery object in it. And each gallery has Brands in it. Like this,

Gallery1.Brandlist => Audi, Ford 
Gallery2.BrandList => Mercedes,Volvo 
Gallery3.BrandList => Subaru 
Gallery4.BrandList => Renault 
Gallery5.BrandList => Subaru 
Gallery6.BrandList =>

What I am trying to get with LINQ is a list of Brands that are distinct of all above's first brand only(so I won't take Ford and Volvo even they are in the list). A gallery doesn't have to have a Brand in their list. So it might be empty as Gallery6. The Output should be,

{Audi, Mercedes, Subaru, Renault}

I don't know how I can do this with LINQ. I tried SelectMany but all I can do with LINQ is simple (p=>p.Something = (int) something).ToList(). I couldn't figure out how to do it.

Upvotes: 2

Views: 70

Answers (2)

Tim Schmelter
Tim Schmelter

Reputation: 460138

Use SelectMany and Distinct:

IEnumerable<string> allUniqueBrands = allGalleries
    .SelectMany(g => g.BrandList.Select(b => b.Name)).Distinct();

In query syntax:

IEnumerable<string> allBrands = from gallery in allGalleries
                                from brand in gallery.BrandList
                                select brand.Name;
IEnumerable<string> allUniqueBrands = allBrands.Distinct();

Edit: Now i got it, you need only the first brands of each BrandList.

If you want to select the Brand you have to provide a custom IEqualityComparer<Brand> which you can use in Distinct. If you neeed a List<Brand>, just call ToList() at the end.

Here's an IEqualityComparer<Brand> for Distinct (or Union,Intesect,Except etc):

public class BrandComparer : IEqualityComparer<Brand>
{
    public bool Equals(Brand x, Brand y)
    {
        if (x == null || y == null) return false;
        return x.Name.Equals(y.Name, StringComparison.OrdinalIgnoreCase);
    }

    public int GetHashCode(Brand obj)
    {
        if (obj == null) return int.MinValue;
        return obj.Name.GetHashCode();
    }
}

and here's the distinct list of all (first) brands:

List<Brand> uniqueFirstBrands = allGalleries
    .Where(g => g.BrandList != null && g.BrandList.Any())
    .Select(g => g.BrandList.First())
    .Distinct(new BrandComparer())
    .ToList();

Upvotes: 4

digEmAll
digEmAll

Reputation: 57210

This should work:

var brands = galleries.Where(x => x.BrandList.Any())
                      .Select(x => x.BrandList.First().Name)
                      .Distinct();

If you want the result being a collection of Brand objects instead of strings, you could do this:

var brands = galleries.Where(x => x.BrandList.Any())
                      .GroupBy(x => x.BrandList.First().Name)
                      .Select(g => g.First().BrandList.First());

Upvotes: 3

Related Questions