2012-09-06 12 views
5

Ich versuche, eine Anzahl von Eltern ohne Kinder plus Eltern Kinder zu bekommen. Während ich dies schreibe merke ich, es besser ist, mit dem Code erklärt .. So, hier geht es:Graf von abgeflacht Elternteil Kindervereinigung in LINQ

Mit diesen Beispiel-Typen:

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

Und diese Daten:

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 

Ich versuche, um eine Anzahl von 3 zurück zu bekommen.

Vielen Dank im Voraus für Ihre Hilfe.

-Jessy Houle

Hinzugefügt nach:

ich mit allen großen (und schnell) Antworten war sichtlich beeindruckt. Für andere, die zu dieser Frage kommen und nach ein paar Optionen suchen, ist hier ein Komponententest mit einigen der Arbeitsbeispiele von unten.

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

Nochmals vielen Dank für Ihre Hilfe!

+1

+1 für die Bereitstellung nützlicher Beispielcode. – sloth

Antwort

5

Wie wäre es

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

Vielleicht habe ich einen Teil der Frage verpasst, aber warum die 'Math.Max'? –

+0

Ich denke, ich kann meine Frage selbst beantworten: weil 'Orders.Count()' möglich ist, könnte 0 sein, aber es sollte als 1 gezählt werden (weil alle Kunden gezählt werden sollen). +1 –

+0

In der Industrie ist die Geschwindigkeit auf den Markt sehr wichtig. Danke, für die schnelle Antwort. –

0

Sie probabbly für so etwas suchen:

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

Wenn Sie statt einer Null, dass Order-Eigenschaft mit einer leeren Liste initialisiert werden würde, könnten Sie tun:


Wenn Sie sich entscheiden, um die nicht initialisierten Eigenschaft zu halten, dann stattdessen tun:

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

Ergebnis die Summe dieser beiden Werte

1

Dies funktioniert, wenn Sie wollen zählen „nein Aufträge“ als 1 und die Aufträge zählen sonst:

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

Durch die wa y, die Frage ist sehr vorbildlich.