I have two classes, let's call them foo
and bar
, that both have a DateTime
property called ReadingTime
.
I then have long lists of these classes, let's say foos
and bars
, where foos
is List<foo>
, bars
is List<bar>
.
My goal is for every element in foos
to find the events in bars
that happened right before and right after foo
.
Some code to clarify:
var foos = new List<foo>();
var bars = new List<bar>();
...
foreach (var foo in foos)
{
bar before = bars.Where(b => b.ReadingTime <= foo.ReadingTime).OrderByDescending(b => b.ReadingTime).FirstOrDefault();
bar after = bars.Where(b => b.ReadingTime > foo.ReadingTime).OrderBy(b => b.ReadingTime).FirstOrDefault();
...
}
My issue here is performance. Is it possible to use some other data structure than a list to speed up the comparisons? In particular the OrderBy
statement every single time seems like a huge waste, having it pre-ordered should also speed up the comparisons, right?
I just don't know what data structure is best, SortedList
, SortedSet
, SortedDictionary
etc. there seem so many. Also all the information I find is on lookups, inserts, delets, etc., noone writes about finding the next closest element so I'm not sure if anything is optimized for that.
I'm on .net core 3.1 if that matters.
Thanks in advance!
Edit: Okay so to wrap this up:
First I tried implementing @derloopkat's approach. For this I figured I needed a data type that could save the data in a sorted order so I just left it as IOrderedEnumerable
(which is what linq returns). Probably not very smart, as that actually brought things to a crawl. I then tried going with SortedList
. Had to remove some duplicates first which was no problem in my case. Thanks for the help @Olivier Rogier! This got me up to roughly 2x the original performance, though I suspect it's mostly the removed linq OrderBy
s. For now this is good enough, if/when I need more performance I'm going to go with what @CamiloTerevinto suggested.
Lastly @Aldert thank you for your time but I'm too noob and under too much time pressure to understand what you suggested. Still appreciate it and might revisit this later.
Edit2: Ended up going with @CamiloTerevinto's suggestion. Cut my runtime down from 10 hours to a couple of minutes.