gwizardry
gwizardry

Reputation: 511

LINQ query finding object with closest data variable to query input variable

I have a List where UserObj has a DateTime data member and a string Name member. I want to find the UserObj in the list with given Name InputName and with DateTime closest to an input DateTime InputDT

The Names and DateTimes may both occur but there will be a unique solution.

I thought about:

UserObj user = userObjList.Where(u => ((u.Name ==inputName) && (userObjList.Min())).ToList()[0];

But not sure how to specify the minimum condition?

Upvotes: 1

Views: 868

Answers (2)

Tim Rogers
Tim Rogers

Reputation: 21713

Sort them by the absolute difference between the two dates, then take the first.

UserObj user = userObjList
    .Where(u => u.Name == inputName)
    .OrderBy(u => Math.Abs((u.Date - inputDT).TotalSeconds))
    .First();

or using the MinBy extension:

UserObj user = userObjList
    .Where(u => u.Name == inputName)
    .MinBy(u => Math.Abs((u.Date - inputDT).TotalSeconds));

Upvotes: 8

Chris
Chris

Reputation: 27609

I think the following should work though it is untested...

var validUserObjs = userObjList.Where(u => u.Name ==inputName);
double mintime = validUserObjs.Min(u=>Math.Abs((u.Date-inputDate).TotalSeconds));
var result = validUserObjs.First(u=>Math.Abs((u.Date-inputDate).TotalSeconds)==mintime);

The idea is that it gets the valid userobjs by user first. Then it finds how far the closest date is from the input date. Then it finds the specific item by using that time difference.

Its a lot messier than that given one with order by but it should be O(N) to do it (one pass through the list to find the minimum and then a second pass to get that item). It may need some minor tweaking for errors in my code but the idea is sound. :)

Upvotes: 1

Related Questions