2009-06-29 6 views
0

J'ai les objets suivants:Comment puis-je obtenir les éléments distincts de la structure de données suivante en C#/LINQ?

public class Agency 
{ 
    public int ID; 
    public IEnumerable<BusinessUnit> BusinessUnits; 
} 

public class BusinessUnit 
{ 
    public int ID; 
    public decimal AmountSpent; 
    public IEnumerable<Client> Clients; 
} 

public class Client 
{ 
    public int ID; 
    public decimal AmountSpent; 
} 

maintenant, je IEnumerable <Agency> qui contient plusieurs organismes, ces organismes contiennent plusieurs SECTEURSD'ACTIVITÉS, et ces SECTEURSD'ACTIVITÉS contiennent plusieurs clients.

Il pourrait ressembler à:

Agence1
++ BusinessUnit1 - 20
$ ++++ Client1 - 10 $
++++ Client2 - 10 $

Agence2
+ + BusinessUnit2 - 20 $
++++ Client1 - 20 $

Agence 3
++ BusinessUnit1 - 10 $
++++ client5 - 5 $
++++ Client6 - 5
$ ++ BusinessUnit2 - 25 $
++++ Client1 - 25 $

Maintenant, ce que je cherche à faire, est de créer une liste de BusinessUnits et de clients, mais pour toutes les agences, sans doublons.

Donc, je suis à la recherche de transformer cette liste des agences dans:

Toutes les agences
++ BusinessUnit1 - 30
$ ++++ Client1 - 10
$ ++++ Client2 - 10 $
++++ client5 - 5
$ ++++ Client6 - 5

$ ++ BusinessUnit2 - 45
$ ++++ Client1 - 20$ ++++ Client1 - 25 $

Là où j'ai simplement une liste de SECTEURSD'ACTIVITÉS uniques (avec leur total AmountSpent correcte dans tous les cas de ce BusinessUnit particulier), et une liste de clients uniques en eux, avec le montant AmountSpent correct pour chaque instance de ce client particulier sous cette unité commerciale.

Est-il possible avec LINQ que je puisse interroger ma liste IEnumerable <Agency> Agences pour retourner ma liste distincte de combinaisons BusinessUnit/Client avec les sommes correctes?

+0

@Alan, corrigez. Agency.BusinessUnits ne dispose que d'un BusinessUnitID – KingNestor

+0

@Alan, mais vous pouvez avoir Client1 à deux endroits différents parmi 2 BusinessUnits différents. – KingNestor

Répondre

2

Quelque chose comme ça, methinks (non testé):

var res = agencies.SelectMany(a => a.BusinessUnits) 
        .GroupBy(b => b.ID) 
        .Select(b => new BusinessUnit { 
        ID = b.Key, 
        AmountSpent = c.Sum(b2 => b2.AmountSpent), 
        Clients = b.SelectMany(b2 => b2.Clients) 
           .GroupBy(c => c.ID) 
           .Select(c => new Client { 
            ID = c.Key, 
            AmountSpent = c.Sum(c2 => c2.AmountSpent) 
           }) 
        }); 

Il peut y avoir un moyen d'optimiser la création de loin classe anonyme. Je vais laisser ça à vous. En supposant que BusinessUnit.AmountSpent est correct, nous n'avons probablement pas besoin de résumer le montant dépensé par le client.


Sur une deuxième lecture, il semble que vous ne voulez pas effondrer les clients sous unités d'affaires mais gardez chaque cas, dans ce cas, vous pouvez vous débarrasser de b.SelectMany (b2 => b2.Clients) et tout cela suit et juste utiliser b.Clients.

1
var groupings = 
    from agency in agencies 
    from businessUnit in agency.BusinessUnits 
    from client in businessUnit.Clients 
    group client by businessUnit.ID into clients 
    select clients; 

var businessUnits = 
    from grouping in groupings 
    select new 
    { 
     ID = grouping.Key, 
     AmountSpent = grouping.Sum(client => client.AmountSpent), 
     Clients = grouping 
    }; 

Console.WriteLine("All Agencies"); 

foreach (var businessUnit in businessUnits) 
{ 
    Console.WriteLine("++BusinessUnit{0} - ${1}", 
         businessUnit.ID, 
         businessUnit.AmountSpent); 

    foreach (var client in businessUnit.Clients) 
    { 
     Console.WriteLine("++++Client{0} - ${1}", client.ID, client.AmountSpent); 
    } 
} 
+0

@Joe Chung, très gentil! Si BusinessUnit avait une propriété "Nom", comment l'inclurais-je dans le résultat? Ici, je vois que vous accédez à la "clé", mais puisque vous ne pouvez le faire que pour un, comment cela changerait-il si vous aviez aussi besoin d'une chaîne appelée "Nom" de BusinessUnit et Client? – KingNestor

+1

Dans ce cas, vous pouvez créer une nouvelle clé composée: grouper le client par new {businessUnit.ID, businessUnit.Name} dans les clients – Talljoe

Questions connexes