Yves
Yves

Reputation: 211

Two different data types in a foreach loop

Currently I am programming an application using Entity Framework and LINQ. Below I have created a method CarsRow which assigns different results to properties. Then a list is filled using a foreach loop.

Everything currently only works with one parameter (in this case is Cars).

The problem: How can I include a second parameter(data type) and then fill the list carList with it. For example, the Colors class. At the end an Excel table should be created containing data from different EF classes.

private void Main()
{
    var rows = new List<ObjectContactsRow>();

    List<Cars> carList = new List<Cars>();

    carList = _ctx.Objekte.OrderBy(p => p.Nummer).ToList();

    //how can i integrate the data of class Colors in the loop together with the class Cars   

    foreach (var cars in carList)
    {
        var line = rows.Any() ? rows.Max(p => p.LineNumber) + 1 : 2;
        var newrow = CreateNewRow(cars, "parameter of type Colors", line);
        rows.Add(newrow);
    }

    CreateExcelFile(rows);
}

private CarsRow CreateNewRow(Cars obj, Colors col, int line)
{
    var objCars = obj.Cars;
    var colColor = col.Colors;

    return new CarsRow(line)
    {
        Cars = objCars,
        Colors = colColor,
    };
}

Upvotes: 1

Views: 1038

Answers (1)

Dai
Dai

Reputation: 155698

It sounds like you want the Cartesian Product of all Cars with all Colors as a ValueTuple<Car,Color>.

To do a Cartesian Product of any two lists Foo and Bar in Linq do this:

// (This approach uses the extension method syntax instead of the C# keywords `from`, `join`, etc)
// Type names have been added to lambda functions to make it obvious what the values are.

IEnumerable<Foo> fooValues = ...
IEnumerable<Bar> barValues = ...

IEnumerable< ( Foo, Bar ) > cartesianProduct = fooValues
    .SelectMany( Foo foo => barValues, ( Foo foo, Bar bar ) => /* the following syntax creates a new ValueTuple in C# 7: */ ( foo, bar ) );

// or more succinctly (removing unnecessary type names):
var cartesianProduct = fooValues
    .SelectMany( foo => barValues, ( foo, bar ) => ( foo, bar ) );

In your case:

List<Car> cars = _ctx.Objekte
    .OrderBy( c => c.Nummer )
    .ToList();

List<Color> colors = // (you haven't shown how you get a List<Color>)

IEnumerable<(Car,Color)> cartesianProduct = cars
    .SelectMany( c => colors, ( car, color ) => ( car, color ) );

You can then iterate over cartesianProduct directly - but I don't think you need to because your CarsRow object is identical to the (Car,Color) ValueTuple object, but if you want to do additional processing then you can do this:

foreach( (Car car, Color color) in cartesianProduct )
{
    // do stuff with `car` and `color`
} 

Upvotes: 1

Related Questions