Rebuilding the Enterprise - Software, Hardware and Peopleware Migrations for the Systems Architect

2/25/2014

LINQ Sequential Selects for Conditional Joins

2/25/2014 Posted by William Berry No comments
I just finished a block of code that, while not ground breaking, is well worth recording.  The problem setup is:

List<Foo> and List<Bar> conditionally joined to produce List<T>

What data we join on, however, is conditional on a property x of Foo being in List<Bar>.  Let's get a bit more concrete with our example since I hate completely abstract examples.

I have a List<AppetizerItems>, my wife has a List<DinnerItems>.  So lets put together our List<possibleMenu> with a few caveats.  We would like to only go shopping at one store, be able to set the oven to one temperature and if the appetizer has has a wine, it would be nice if the dinner and appetizer shared the same color wine (i.e. red, white, rose, etc.).

var menu = appetizerItems
    .Where( appetizerItem =>
        dinnerItems.Any(
            dinnerItems =>
                dinnerItems.Store == appetizerItem.Store
                && dinnerItems.OvenTemperature == appetizerItem.OvenTemperature
        )
    .Select( appetizerItem => new
    {
        appetizerItem,
        dinnerItem = (
            dinnerItems.Any(di => di.HasWine == appetizerItem.HasWine
            ? dinerItems.First(di =>
                di.Store == appetizerItem.Store
                && di.OvenTemperature == appetizerItem.OvenTemperature
                && di.GrapeColor == appetizerItem.GrapeColor
            )
            :  dinnerItems.First(di =>
                di.Store == appetizerItem.Store
                && di.OvenTemperature == appetizerItem.OvenTemperature
    })
    .Select(possibleMenu =>  new
    {
        possibleMenu.appetizerItem.AppetizerItems,
        possibleMenu.dinnerItem.DinnerItems,
        ...
    });

As you can see, we have managed to do a conditional join via anonymous object composition and sequential selects.

0 comments:

Post a Comment