2012-09-06 13 views
5

Próbuję uzyskać liczbę rodziców bez dzieci i rodziców dzieci. Kiedy piszę to zdaję sobie sprawę, że jest lepiej wyjaśnione z kodem .. Więc tu idzie:Liczba spłaszczonych skojarzeń dzieci w LINQ

Z tych przykładowych typów:

public class Customer 
{ 
    public int Id { get; set; } 
    public string Name { get; set; } 
    public List<Order> Orders { get; set; } 
} 

public class Order 
{ 
    public int Id { get; set; } 
    public string Description { get; set; } 
} 

a dane:

var customers = new List<Customer> 
{ 
    new Customer 
    { 
     Id = 2, 
     Name = "Jane Doe" 
    }, 
    new Customer 
    { 
     Id = 1, 
     Name = "John Doe", 
     Orders = new List<Order> 
     { 
      new Order { Id = 342, Description = "Ordered a ball" }, 
      new Order { Id = 345, Description = "Ordered a bat" } 
     } 
    } 
}; 

// I'm trying to get a count of customer orders added with customers with no orders 
// In the above data, I would expect a count of 3 as detailed below 
// 
// CId  Name  OId 
// ----  -------- ---- 
// 2  Jane Doe 
// 1  John Doe 342 
// 1  John Doe 345 

int customerAndOrdersCount = {linq call here}; // equals 3 

usiłuję aby uzyskać 3 z powrotem.

Z góry dziękujemy za pomoc.

-Jessy Houle

Dodano po:

Byłem naprawdę pod wrażeniem wszystkich wielkich (i szybki) odpowiedzi. Dla innych, którzy przychodzą na to pytanie, szukając kilku opcji, tutaj jest test jednostkowy z kilkoma przykładami pracy poniżej.

[TestMethod] 
public void TestSolutions() 
{ 
    var customers = GetCustomers(); // data from above 

    var count1 = customers.Select(customer => customer.Orders).Sum(orders => (orders != null) ? orders.Count() : 1); 
    var count2 = (from c in customers from o in (c.Orders ?? Enumerable.Empty<Order>()).DefaultIfEmpty() select c).Count(); 
    var count3 = customers.Sum(c => c.Orders == null ? 1 : c.Orders.Count()); 
    var count4 = customers.Sum(c => c.Orders==null ? 1 : Math.Max(1, c.Orders.Count())); 


    Assert.AreEqual(3, count1); 
    Assert.AreEqual(3, count2); 
    Assert.AreEqual(3, count3); 
    Assert.AreEqual(3, count4); 
} 

Jeszcze raz, dziękuję wszystkim za pomoc!

+1

+1 za udostępnienie przydatnego kodu egzaminu. – sloth

Odpowiedz

5

Jak o

int customerAndOrdersCount = customers.Sum(c => c.Orders==null ? 1 : Math.Max(1, c.Orders.Count())); 
+1

Może przegapiłem część pytania, ale dlaczego "Math.Max"? –

+0

Myślę, że mogę odpowiedzieć na moje pytanie sam: ponieważ 'Orders.Count') może być 0, ale powinno być liczone jako 1 (ponieważ wszyscy klienci będą policzeni). +1 –

+0

W branży, szybkość na rynek jest BARDZO ważna. Dziekuje za szybką odpowiedź. –

0

Ty probabbly szukając coś takiego:

customers.GroupBy(customer=>customer). //group by object iyself 
     Select(c=>      //select 
        new 
        { 
         ID = c.Key.Id,        
         Name = c.Key.Name, 
         Count = (c.Key.Orders!=null)? c.Key.Orders.Count():0 
        } 
       ); 
1

Jeśli chcesz zainicjować tę właściwość Order z pustą listą zamiast null, można zrobić:

int count = 
    (
    from c in customers 
    from o in c.Orders.DefaultIfEmpty() 
    select c 
).Count(); 

Jeśli zdecydujesz się zachować własność niezainicjowanej dookoła, wówczas zamiast zrobić:

int count = 
    (
    from c in customers 
    from o in (c.Orders ?? Enumerable.Empty<Order>()).DefaultIfEmpty() 
    select c 
).Count(); 
1
customers 
    .Select(customer => customer.Order) 
    .Sum(orders => (orders != null) ? orders.Count() : 1) 
0
var orderFreeCustomers = customers.Where(c=>c.Orders== null || c.Orders.Any()==false); 

var totalOrders = customers.Where (c => c.Orders !=null). 
Aggregate (0,(v,e)=>(v+e.Orders.Count) ); 

Wynik jest sumą tych dwóch wartości

1

to działa, jeśli chcesz liczyć „nie zlecenia” jako 1 i policzyć zamawia inaczej:

int customerOrders = customers.Sum(c => c.Orders == null ? 1 : c.Orders.Count()); 

Wg wa y, pytanie jest bardzo przykładne.

Powiązane problemy