Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Convert double for-loop into a linq query

I have a loop which, once simplified, looks like this:

Dictionary<Tuple<A,G>,Decimal> results = new Dictionary<Tuple<A,G>,Decimal>();
foreach( A a in collectionA )
    foreach( B b in collectionB )
        results [Tuple.Create(a, (G)b.groupBy)] += (Decimal) Func(a, b);

Is there a way I can replicate this result using a Linq query (with GroupBy, Sum and ToDictionary for example)? (as suggested in this answer to a previous question: Concise way to do a plus equals operation on a Dictionary element that might not be initialized)


Result

//Dictionary<EventGroupIDLayerTuple, Decimal> BcEventGroupLayerLosses

Using Yuxiu Li's answer below, I was able to convert this 4 liner from the linked question:

BcEventGroupLayerLosses = new Dictionary<EventGroupIDLayerTuple, Decimal>();
foreach( UWBCEvent evt in this.BcEvents.IncludedEvents )
    foreach( Layer lyr in this.ProgramLayers )
        BcEventGroupLayerLosses.AddOrUpdate(
            new EventGroupIDLayerTuple(evt.EventGroupID, lyr),
            GetEL(evt.AsIfs, lyr.LimitInMillions, lyr.AttachmentInMillions), 
            (a, b) => a + b);

into this one liner:

BcEventGroupLayerLosses = this.BcEvents.IncludedEvents
    .SelectMany(evt => ProgramLayers, (evt, lyr) => new { evt, lyr })
    .GroupBy(g => new EventGroupIDLayerTuple(g.evt.EventGroupID, g.lyr), 
      g => GetEL(g.evt.AsIfs, g.lyr.LimitInMillions, g.lyr.AttachmentInMillions))
    .ToDictionary(g => g.Key, g => g.Sum());

And both yielded identical results.

Granted neither is particularly readable, this was a good experiment. Thanks everyone for your help!

like image 772
Alain Avatar asked May 24 '26 00:05

Alain


1 Answers

Dictionary<Tuple<A, G>, decimal> dictionary =
            (from a in collectionA
             from b in collectionB
             group (decimal)Func(a, b) by Tuple.Create<A, G>(a, b.groupBy))
            .ToDictionary(g => g.Key, g => g.Sum());

In declarative synatax

var dictionary = collectionA
    .SelectMany(a => collectionB,
                (a, b) => new { a, b })
    .GroupBy(g => Tuple.Create(g.a, g.b.groupBy),
             g => Func(g.a, g.b))
    .ToDictionary(g => g.Key, g => g.Sum());
like image 107
Todd Li Avatar answered May 25 '26 12:05

Todd Li



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!