2012-09-06 13 views
5

Estoy tratando de obtener un recuento de los padres sin hijos más padres e hijos. Mientras escribo esto me doy cuenta de que es mejor explicado con código .. Por lo tanto, aquí va:Recuento de la asociación aplastada de padres y niños en LINQ

Con este tipo de ejemplo:

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

Y estos datos:

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 

estoy tratando para obtener un conteo de 3 de vuelta.

Gracias de antemano por su ayuda.

-Jessy Houle

Alta después:

me quedé realmente impresionado con todos los grandes (y rápido) respuestas. Para otros que se acerquen a esta pregunta, buscando algunas opciones, aquí hay una Prueba de unidad con algunos de los ejemplos de trabajo de abajo.

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

Nuevamente, ¡gracias a todos por su ayuda!

+1

+1 para proporcionar un código de ejemplo útil. – sloth

Respuesta

5

¿Qué tal

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

Tal vez me he perdido una parte de la pregunta, pero ¿Por qué 'Math.Max'? –

+0

Creo que puedo responder mi pregunta por mi cuenta, porque 'Orders.Count()' posible podría ser 0, pero debería contarse como 1 (porque se contarán todos los clientes). +1 –

+0

En la industria, la velocidad de comercialización es MUY importante. Gracias por la rápida respuesta. –

0

Usted probabbly en busca de algo como esto:

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

Si desea inicializar esa propiedad Orden con una lista vacía en lugar de un valor nulo, se podría hacer:

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

Si decide mantener la propiedad sin inicializar nada más, entonces en vez de hacer:

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

El resultado es la suma de estos dos valores

1

Esto funciona si se desea contar "sin órdenes" como 1 y contar las órdenes de otro modo:

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

Por el wa y, la pregunta es muy ejemplar.

Cuestiones relacionadas