2009-06-29 3 views
0

나는 다음과 같은 개체가 :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; 
} 

지금, 나는 IEnumerable을 <Agency이> 여러 기관을 포함, 이들 기관은 여러 BusinessUnits를 포함, 그 BusinessUnits는 여러 클라이언트가 포함되어 있습니다.

그것은 같은 것을 볼 수 있습니다

Agency1을
++ BusinessUnit1 - $ (20)
++++ 클라이언트 1 - $ (10)
++++ 클라이언트 2 - $ (10)

Agency2
+ + BusinessUnit2 - $ 20
++++ 고객 1 - $ 20

대행사 3
++ BusinessUnit1 - $ (10)
++++ Client5 - $ (5)
++++ Client6 - $ (5)
++ BusinessUnit2 - $ (25)
++++ 클라이언트 1 - 이제 $ (25)

, 내가하고자하는 일은 BusinessUnits 및 Clients 목록을 만드는 것입니다.하지만 모든 대행사는 중복되지 않습니다.

그래서, 나는에 기관의 목록을 설정하는 찾고 있어요 :

모든 기관
++ BusinessUnit1 - $ (30)
++++ 클라이언트 1 - $ (10)
++++ 클라이언트 2 - $ (10)
++++ Client5 - $ (5)
++++ Client6 - $ (5)

++ BusinessUnit2 - $ (45)
++++ 클라이언트 1 - $ (20)
++++ 클라이언트 1 - 단순히 (특정 BusinessUnit의 모든 인스턴스에서 올바른 AmountSpent의 총) 독특한 BusinessUnits의 목록을 어디에서 $ (25)

, 그 아래 고유의 클라이언트 목록과 함께 해당 비즈니스 단위 아래에있는 해당 특정 클라이언트의 각 인스턴스에 대한 정확한 AmountSpent 총계.

LINQ에서 IEnumerable <Agency> 기관 목록을 조회하여 BusinessUnit/Client 조합의 고유 목록을 정확한 합계로 반환 할 수 있습니까? , ...이라고 생각되다 (안된)이 같은

+0

@Alan. Agency.BusinessUnits에는 각각 BusinessUnitID – KingNestor

+0

@ Alan 중 하나만 있지만 두 개의 다른 BusinessUnits 중 두 곳에서 Client1이있을 수 있습니다. – KingNestor

답변

2

뭔가 :

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
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, 아주 멋지다! BusinessUnit에 "Name"속성이 있으면 어떻게 결과에 포함시킬 수 있습니까? 여기에서는 "키"에 액세스하는 것을 볼 수 있지만 하나만 할 수 있기 때문에 BusinessUnit 및 Client에서 "Name"이라는 문자열이 필요한 경우 어떻게 변경됩니까? – KingNestor

+1

그런 경우 새로운 복합 키를 작성할 수 있습니다. new (businessUnit.ID, businessUnit.Name)를 클라이언트로 그룹화하십시오. – Talljoe