Как я могу получить отдельные элементы следующей структуры данных в C # / LINQ? - PullRequest
0 голосов
/ 30 июня 2009

У меня есть следующие объекты:

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;
}

Теперь у меня есть IEnumerable <Agency>, который содержит несколько агентств, эти агентства содержат несколько BusinessUnits, и эти BusinessUnits содержат несколько клиентов.

Это может выглядеть примерно так:

Агентства1
++ BusinessUnit1 - $ 20
++++ Client1 - $ 10
++++ Client2 - $ 10

Agency2
++ BusinessUnit2 - $ 20
++++ Client1 - $ 20

Agency3
++ BusinessUnit1 - $ 10
++++ Client5 - $ 5
++++ Client6 - $ 5
++ BusinessUnit2 - $ 25
++++ Client1 - $ 25

Теперь я собираюсь создать список BusinessUnits и Clients, но для всех агентств, без дубликатов.

Итак, я хочу превратить этот список агентств в:

Все агентства
++ BusinessUnit1 - $ 30
++++ Client1 - $ 10
++++ Client2 - $ 10
++++ Client5 - $ 5
++++ Client6 - $ 5

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

Где у меня просто есть список уникальных BusinessUnit (с их правильной суммой AmountSpent для всех экземпляров этого конкретного BusinessUnit) и со списком уникальных клиентов под ними, с правильной суммой AmountSpent для каждого экземпляра этого конкретного клиента в это бизнес-единица.

Возможно ли с LINQ, что я могу запросить мой список агентств IEnumerable <Agency>, чтобы вернуть мой отдельный список комбинаций BusinessUnit / Client с правильными суммами?

Ответы [ 2 ]

2 голосов
/ 30 июня 2009

Примерно так, метинкс (не проверено):

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) 
                                 })
                   });

Может быть способ оптимизировать создание анонимного класса. Я оставлю это на ваше усмотрение. Предполагая, что BusinessUnit.AmountSpent верен, нам, вероятно, не нужно суммировать AmountSpent Клиента.


При втором чтении может показаться, что вы, возможно, не захотите сворачивать клиентов под подразделениями, но сохраните каждый экземпляр, в этом случае вы можете избавиться от b.SelectMany (b2 => b2.Clients) и всего, что следует использовать b.Clients.

1 голос
/ 30 июня 2009
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);
    }
}
...