Filter a list by a property that is a list with items from another list with Linq

0

I have a list of objects (Invoices) that have a property that in turn is also a list (DetailFactura) of objects of LineaFactura type. On the other hand I have a list of strings that represent the items by which to filter. It would be something like this:

 public class LineaFactura
   {
      public int NumLinea { get; set; }
      public int Cantidad { get; set; }
      public string Producto { get; set; }
      public int Precio { get; set; }
   }

   public class Factura
   {
      public int NumFactura { get; set; }
      public List<LineaFactura> DetalleFactura { get; set; }
   }

   class Program
   {
      static void Main(string[] args)
      {
         List<Factura> facturas = new List<Factura>();
         Factura factura = null;
         List <LineaFactura> lineasFactura = null;
         LineaFactura lineafactura = null;

         factura = new Factura();
         factura.NumFactura = 1;
         lineasFactura = new List<LineaFactura>();
         lineafactura = new LineaFactura() { NumLinea = 1, Cantidad = 1, Producto = "Prod1", Precio = 2 };
         lineasFactura.Add(lineafactura);
         lineafactura = new LineaFactura() { NumLinea = 2, Cantidad = 1, Producto = "Prod2", Precio = 3 };
         lineasFactura.Add(lineafactura);
         facturas.Add(factura);

         factura = new Factura();
         factura.NumFactura = 2;
         lineasFactura = new List<LineaFactura>();
         lineafactura = new LineaFactura() { NumLinea = 1, Cantidad = 1, Producto = "Prod3", Precio = 5 };
         lineasFactura.Add(lineafactura);
         facturas.Add(factura);

         factura = new Factura();
         factura.NumFactura = 3;
         lineasFactura = new List<LineaFactura>();
         lineafactura = new LineaFactura() { NumLinea = 1, Cantidad = 1, Producto = "Prod1", Precio = 2 };
         lineasFactura.Add(lineafactura);
         lineafactura = new LineaFactura() { NumLinea = 2, Cantidad = 1, Producto = "Prod3", Precio = 3 };
         lineasFactura.Add(lineafactura);
         facturas.Add(factura);

         List<string> listaProductos = new List<string>() { "Prod1", "Prod3" };

         //Aquí filtro las facturas por la lista de productos
         var listaFacturas = facturas.??????

         //En listaFacturas debería tener:
         /*
          * Factura 1 Linea 1
          * Factura 3 Linea 1
          * Factura 3 Linea 3
          */

      }
   }

What I need is to obtain the invoices and their lines that have the product in the filter list through a single Linq instruction if possible. In the example, as indicated in the comments, should only be:

Bill 1 Line 1
Invoice 3 Line 1
Invoice 3 Line 3

Thank you.

    
asked by Carlos 24.10.2017 в 12:38
source

1 answer

0

You can do it using the SelectMany method.

In your code you also need to associate the invoice lines to the property DetalleFactura :

List<Factura> facturas = new List<Factura>();
Factura factura = null;
List<LineaFactura> lineasFactura = null;
LineaFactura lineafactura = null;

factura = new Factura();
factura.NumFactura = 1;
lineasFactura = new List<LineaFactura>();
lineafactura = new LineaFactura() { NumLinea = 1, Cantidad = 1, Producto = "Prod1", Precio = 2 };
lineasFactura.Add(lineafactura);
lineafactura = new LineaFactura() { NumLinea = 2, Cantidad = 1, Producto = "Prod2", Precio = 3 };
lineasFactura.Add(lineafactura);
factura.DetalleFactura = lineasFactura;
facturas.Add(factura);

factura = new Factura();
factura.NumFactura = 2;
lineasFactura = new List<LineaFactura>();
lineafactura = new LineaFactura() { NumLinea = 1, Cantidad = 1, Producto = "Prod3", Precio = 5 };
lineasFactura.Add(lineafactura);
factura.DetalleFactura = lineasFactura;
facturas.Add(factura);

factura = new Factura();
factura.NumFactura = 3;
lineasFactura = new List<LineaFactura>();
lineafactura = new LineaFactura() { NumLinea = 1, Cantidad = 1, Producto = "Prod1", Precio = 2 };
lineasFactura.Add(lineafactura);
lineafactura = new LineaFactura() { NumLinea = 2, Cantidad = 1, Producto = "Prod3", Precio = 3 };
lineasFactura.Add(lineafactura);
factura.DetalleFactura = lineasFactura;
facturas.Add(factura);

List<string> listaProductos = new List<string>() { "Prod1", "Prod3" };

// Si lo que quires es obtener las líneas de factura que tengan alguno de los productos
Console.WriteLine("Líneas");
var lineas = facturas.SelectMany(
        f => f.DetalleFactura.Select(l => new {f.NumFactura, l.NumLinea, l.Producto}))
    .Where(l => listaProductos.Contains(l.Producto));
foreach (var linea in lineas)
{
    Console.WriteLine($"Factura {linea.NumFactura} Línea {linea.NumLinea} {linea.Producto}");
}

Console.WriteLine("\nFacturas");
// Para sacar una lista de facturas únicamente con las líneas del filtro
var facturasFiltradas = facturas.Where(f => f.DetalleFactura.Any(l => listaProductos.Contains(l.Producto)))
    .Select(
        f =>
            new Factura()
            {
                NumFactura = f.NumFactura,
                DetalleFactura = f.DetalleFactura.Where(l => listaProductos.Contains(l.Producto)).ToList()
            });
foreach (var facturaFiltrada in facturasFiltradas)
{
    foreach (var lineaFactura in facturaFiltrada.DetalleFactura)
    {
        Console.WriteLine($"Factura {facturaFiltrada.NumFactura} Línea {lineaFactura.NumLinea} {lineaFactura.Producto}");
    }
}
    
answered by 24.10.2017 / 13:32
source