Kefka
Kefka

Reputation: 89

How to speed up this LINQ query with join?

I have two collections of my object models that I am comparing for inequality on a per-property basis.

ObservableCollection<LayerModel> SourceDrawingLayers

...and:

ObservableCollection<LayerModel> TargetDrawingLayers

I have received great advice on creating the non-equijoin LINQ query in general and have it working in my application to great effect but now I would like to speed it up:

var onOffQuery = from target in TargetDrawingLayers
                 from source in SourceDrawingLayers
                 where target.Name == source.Name && target.OnOff != source.OnOff
                 select target;

My understanding is I am multiplying my query by the number of items in the source drawing * the number of items in the target drawings * the number of target drawings that I populated into TargetDrawingLayers.

I would like to speed up this operation using Join but I'm running into issues with the != part of it.

I played around with this:

var newQuery = from source in SourceDrawingLayers
    join target in TargetDrawingLayers
    on target.name
    where target.OnOff != source.OnOff
    select target;

But I'm struggling with the syntax. Can someone set me on the right track with it?

Also, will this even be a noticeable performance improvement?

Upvotes: 3

Views: 546

Answers (2)

Theodor Zoulias
Theodor Zoulias

Reputation: 43495

Maybe what you need is to join on the combination of the properties Name and OnOff. The combination can be expressed as a ValueTuple:

var newQuery = from source in SourceDrawingLayers
               join target in TargetDrawingLayers
               on (source.Name, source.OnOff) equals (target.Name, !target.OnOff)
               select target;

Upvotes: 0

Igor
Igor

Reputation: 62213

Replace on target.name with on source.name equals target.name

var newQuery = from source in SourceDrawingLayers
         join target in TargetDrawingLayers
         on source.name equals target.name
         where target.OnOff != source.OnOff
         select target;

In Linq-to-objects the join will create a Lookup<TKey,TElement> on the join properties which will result in a performance improvement when matching the source and target. Assuming that this results on a restricted result set it should improve the original code quit a bit. Of course if it results in many matches because name contains a very limited range of values on both sides then the performance will not be effected much at all.

As a reference please see the link to the Enumerable.cs source code that was provided in the comments below by juharr.

Upvotes: 5

Related Questions