2017-06-23 3 views
1

Ich habe etwas arbeiten in einfachen Simpel-Schleifen, aber ich möchte, wie es mit LINQ, wenn möglich zu tun.Wie man eine gruppierte distinct in linq

Ich weiß nicht einmal, wie ich beschreiben soll, was ich tun möchte. Aber Stack-Überlauf will, dass ich so in Worte tun, anstatt mit einem Beispiel, so ist dies mich austricksen ...

Die Klassen (abgespeckte)

public class Product 
{ 

    public int ProductId { get; set; } 
    public string Name { get; set; } 
    public List<CategoryGroup> CategoryGroups { get; set; } 
} 

public class CategoryGroup 
{ 
    public int CategoryGroupId { get; set; } 
    public string Name { get; set; } 
    public List<Category> Categories { get; set; } 
} 

public class Category 
{ 
    public int CategoryId { get; set; } 
    public string Name { get; set; } 
} 

Was ich tun möchte,

Von

Product 1 
    CategoryGroup 1 
     Category 11 
     Category 12 
     Category 13 
    CategoryGroup 2 
     Category 21 
     Category 22 

Product 2 
    Category Group 1 
     Category 11 
     Category 14 
    Category Group 2 
     Category 21 
    Category Group 3 
     Category 31 

Um

Category Group 1 
    Category 11 
    Category 12 
    Category 13 
    Category 14 
Category Group 2 
    Category 21 
    Category 22 
Category Group 3 
    Category 31 

Der Arbeitscode

var categoryGroups = new List<CategoryGroup>(); 
foreach (var product in products) 
{ 
    foreach (var categoryGroup in product.CategoryGroups) 
    { 
     var group = categoryGroups.SingleOrDefault(cg => cg.CategoryGroupId == categoryGroup.CategoryGroupId); 
     if (group == null) 
     { 
      group = new CategoryGroup { 
       Categories = new List<Category>(), 
       CategoryGroupId = categoryGroup.CategoryGroupId, 
       Name = categoryGroup.Name 
      }; 
      categoryGroups.Add(group); 
     } 

     foreach (var category in categoryGroup.Categories) 
     { 
      if (group.Categories.Any(c => c.CategoryId == category.CategoryId)) 
      { 
       continue; 
      } 
      group.Categories.Add(category); 
     } 
    } 
} 
+2

Bitte fügen Sie den Code zum Ausfüllen der Beispieldaten bei - damit es Ihnen leichter fällt, Ihnen zu helfen. – mjwills

Antwort

3

Du viele subselections durch Select tun können:

var result = products 
      .SelectMany(x => x.CategoryGroups) 
      .GroupBy(x => x.CategoryGroupId) 
      .Select(x => new CategoryGroup 
         { 
          Categories = x.SelectMany(y => y.Categories) 
              .Distinct(y => y.CategoryId) 
              .OrderBy(y => y.CategoryId) 
              .ToList(), 
          CategoryGroupId = x.Key, 
          Name = x.Values.First().Name 
         }) 
      .OrderBy(x => x.CategoryGroupId) 
      .ToList(); 
+0

Viele Fehler innerhalb des 'Select' nach' GroupBy': 'x.Values',' x.CategoryGroupId', 'x.Name' (keine solchen Members),' Distinct (y => y.CategoryId) '(nicht so Methode Überladung) –

+0

Sorry, repariere es. – eocron

+0

Ich erhalte den folgenden Fehler: IGrouping enthält keine Definition für 'Values' – Migaroez

0

Hier ist die Abfrage alle verschiedenen Kategoriegruppen zu erhalten

var categoryGroups = products.SelectMany(g => g.CategoryGroups) 
            .GroupBy(x => x.CategoryGroupId) 
            .Select(y => new { CategoryGroupId = y.Key, 
                Categories = y.SelectMany(category => category.Categories).Distinct().ToList()           }); 

Um doppelte zu vermeiden aßen Kategorien Sie müssen Ihre Kategorie Objekt modifizieren, um die IEquatable Schnittstelle zu implementieren, wie

public class Category : IEquatable<Category> 
{ 
    public int CategoryId { get; set; } 
    public string Name { get; set; } 

    public bool Equals(Category other) 
    { 
     //Check whether the compared object is null. 
     if (Object.ReferenceEquals(other, null)) return false; 

     //Check whether the compared object references the same data. 
     if (Object.ReferenceEquals(this, other)) return true; 

     //Check whether the products' properties are equal. 
     return CategoryId.Equals(other.CategoryId) && Name.Equals(other.Name); 
    } 

    // If Equals() returns true for a pair of objects 
    // then GetHashCode() must return the same value for these objects. 

    public override int GetHashCode() 
    { 

     //Get hash code for the Name field if it is not null. 
     int hashProductName = Name == null ? 0 : Name.GetHashCode(); 

     //Get hash code for the Code field. 
     int hashProductCode = CategoryId.GetHashCode(); 

     //Calculate the hash code for the product. 
     return hashProductName^hashProductCode; 
    } 
} 

Implementierung der Schnittstelle folgt ermöglicht die Distinct() -Aufruf in LINQ die Liste der Objekte zu vergleichen und Duplikate zu beseitigen.

Hoffe, dass hilft.