Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
126 views
in Technique[技术] by (71.8m points)

c# - Linq query that can use a list of DateTime to filter a List<object>

I am trying to filter a set of data by any weekend, by using using a list of DateTimes, that is created dynamically. The list of DateTimes, has several dates in it, that contain a from date and a to date. This can be for any weekend in the past.

The list of DateTimes looks similar to this:

public class ShiftTimeFilter
{
     public DateTime ShiftTimeFrom { get; set; }
     public DateTime ShiftTimeTo { get; set; }
}

And the dates that created are in a new List<ShiftTimeFilter>(); This creates the following example dates for a given weekend.

[0] ShiftTimeFrom : {23/01/2021 00:30}, ShiftTimeTo : {23/01/2021 16:30}
[1] ShiftTimeFrom : {24/01/2021 17:30}, ShiftTimeTo : {24/01/2021 19:30}

I can do it for one day, i.e. Saturday or a Sunday, but I cannot understand how I can do this using a list of DateTimes to incorporate both days and filter in one go. The myData model is as follows:

public class myData
{
    public DateTime ReadingDate { get; set; }
    public double ReadingValue { get; set; }
}

The query I am using:

   var data = myData.Where(x => x.ReadingDate.DayOfWeek == DayOfWeek.Saturday 
                 && x.ReadingDate > ShiftTimeFrom 
                 && x.ReadingDate <= ShiftTimeFrom )
               .Select(x => new Data { myDate = x.ReadingDate, myVal = x.ReadingValue })
               .ToList();

One of the problems I have is that the customer, may choose a period of time over several months, and they will want to see every weekend for the period of time. So the list of dates can have in some cases 10 or 20 dates in it.

I was hoping to use Linq to filter the dates by saying, give me all of the data that is between all of the dates List<ShiftTimeFilter>; and anything that is not between those dates, I want to set it's value to zero.

TIA

question from:https://stackoverflow.com/questions/65945878/linq-query-that-can-use-a-list-of-datetime-to-filter-a-listobject

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

I would add a bit logic to the filters to simplify the queries. e.g. define an interface IDateTimeFilter:

public interface IDateTimeFilter {

    bool IsMatch(DateTime pointInTime);

}

and adapt the class ShiftTimeFilter to implement it:

public class ShiftTimeFilter : IDateTimeFilter {

    public ShiftTimeFilter(DateTime from, DateTime to) {
        if (from < to) {
            ShiftTimeFrom = from;
            ShiftTimeTo = to;
        } else {
            ShiftTimeTo = from;
            ShiftTimeFrom = to;
        }
    }

    public DateTime ShiftTimeFrom { get; }

    public DateTime ShiftTimeTo { get; }

    public Boolean IsMatch(DateTime pointInTime) {
        return (pointInTime >= ShiftTimeFrom) && (pointInTime < ShiftTimeTo);
    }

}

And create a new class that combines the filters, also implementing the interface:

public class ShiftTimeFilterList : IDateTimeFilter {

    private IDateTimeFilter[] Filters { get; }

    public ShiftTimeFilterList(IEnumerable<IDateTimeFilter> dateTimeFilters) {
        if (dateTimeFilters is null) throw new ArgumentNullException(nameof(dateTimeFilters));
        Filters = dateTimeFilters.Where(e => e is object).ToArray();
    }

    // [Edited: NetMage's simplification implemented]
    public bool IsMatch(DateTime pointInTime) => Filters.Any(filter => filter.IsMatch(pointInTime));

}

Now you can use a simple query like this to get the matching data:

IEnumerable<myData> dataToBeFiltered = GetData();
IDateTimeFilter filter = GenerateFilter();

List<myData> result = dataToBeFiltered.Where(e => filter.IsMatch(e.ReadingDate)).ToList();

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...