简体   繁体   中英

How to sort a list<t> of objects by property with a certain condition in c#

I have this class and in our app and it is used by the driver . When the driver opens the app , it is supposed to show current day schedule with clients pickup time and their destinations.

public class PickUps
{
  public DateTime PickUpTime { get; set; }
  public int PassengerId { get; set; }
  public String PassengerName { get; set; }
  public GeoCoordinate PassengerLocation { get; set; }
}

List<PickUps> objListPickUps = new List<PickUps>();
objListPickUps  = TravelAPI.GetPickupList(int PassenegerId); // fill list of PickUps

Now i want to filter this list by the closest PickUpTime (lets say he opens the app at 11AM and there are pickups scheduled at 10.30AM and 12 Noon it should return the 10.30AM pickup object details. And if the app is opened at 11 AM and pickup was at 10AM and next pickup was at 12Noon then it should return the 10AM object ie when the difference between "current and prev" and "current and next pickup" is same)

I tried below but it doesn't give me the above result i am expecting. Any other condition i need to add ?

var res = objListPickUps.OrderBy( x => (x.PickupTime - DateTimew.Now).Duration).FirstOrDefault();

Duration()是一种方法,而不是属性或字段:

var closestPickup = objListPickUps.OrderBy(x => (x.PickUpTime - DateTime.Now).Duration()).FirstOrDefault(); 

Ok, assuming then what do you want is what did you try (finding a single closest pickup), but did not get a correct result.

First, you should capture DateTime.Now in a variable so it doesn't change during the query.

Now on the subject.

One thing you can do is to add ThenBy(x => x.PickupTime) to your query, which will handle the case with equal differences:

var baseTime = DateTime.Now;
var closestPickUp = objListPickUps
    .OrderBy(x => (x.PickupTime - baseTime).Duration())
    .ThenBy(x => x.PickupTime)
    .FirstOrDefault();

But I would suggest you to not use the above LINQ method, because it's inefficient. There is no need to sort the list ( O(N*log(N) time) in order to find what you need. Instead, you can use a simple loop ( O(N) ) as follows. Let also encapsulate it inside a method:

static PickUps FindClosestPickUp(List<PickUps> pickUpList, DateTime baseTime)
{
    PickUps closestPickUp = null;
    TimeSpan closestDuration = default(TimeSpan);
    foreach (var pickUp in pickUpList)
    {
        var duration = (pickUp.PickUpTime - baseTime).Duration();
        if (closestPickUp == null || closestDuration > duration || (closestDuration == duration && closestPickUp.PickUpTime > pickUp.PickUpTime))
        {
            closestPickUp = pickUp;
            closestDuration = duration;
        }
    }
    return closestPickUp;
}

and the usage will be simple

var closestPickUp = FindClosestPickUp(objListPickUps, DateTime.Now);

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM