可以使用 DateTime 列表过滤 List<object> 的 Linq 查询
Posted
技术标签:
【中文标题】可以使用 DateTime 列表过滤 List<object> 的 Linq 查询【英文标题】:Linq query that can use a list of DateTime to filter a List<object> 【发布时间】:2021-05-02 20:46:26 【问题描述】:我正在尝试使用动态创建的 DateTimes 列表在任何周末过滤一组数据。 DateTimes
的列表中有几个日期,其中包含一个开始日期和一个到日期。这可以是过去的任何一个周末。
DateTimes 列表看起来类似于:
public class ShiftTimeFilter
public DateTime ShiftTimeFrom get; set;
public DateTime ShiftTimeTo get; set;
创建的日期在new List<ShiftTimeFilter>();
这将为给定的周末创建以下示例日期。
[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
我可以做一天,即周六或周日,但我不明白如何使用 DateTimes 列表来合并这两天并一次过滤。 myData 模型如下:
public class myData
public DateTime ReadingDate get; set;
public double ReadingValue get; set;
我正在使用的查询:
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();
我遇到的一个问题是,客户可能会选择几个月的时间段,而他们会希望每个周末都去看看这段时间。因此,日期列表在某些情况下可以包含 10 或 20 个日期。
我希望使用 Linq 来过滤日期,告诉我所有日期之间的所有数据 List<ShiftTimeFilter>;
以及不在这些日期之间的任何数据,我想将它的值设置为零。
TIA
【问题讨论】:
您可能希望动态生成一个包含一堆“OR”表达式的表达式,就像我描述的here 一样,或者简单地为每个日期范围创建一个单独的查询并将它们合并为我在这个非常相似的问题中进行了描述:***.com/a/45556481/120955 您使用的是哪种 LINQ:LINQ to Objects、SQL、EF 6.x、EF Core 2.0 / 2.1 / 3.x / 5.x?如果有数据库,哪个数据库提供者? 【参考方案1】:我会在过滤器中添加一些逻辑来简化查询。例如定义一个接口IDateTimeFilter
:
public interface IDateTimeFilter
bool IsMatch(DateTime pointInTime);
并调整 ShiftTimeFilter
类来实现它:
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);
并创建一个组合过滤器的新类,同时实现接口:
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));
现在您可以使用这样的简单查询来获取匹配数据:
IEnumerable<myData> dataToBeFiltered = GetData();
IDateTimeFilter filter = GenerateFilter();
List<myData> result = dataToBeFiltered.Where(e => filter.IsMatch(e.ReadingDate)).ToList();
【讨论】:
public bool IsMatch(DateTime pointInTime) => Filters.Any(filter => filter.IsMatch(pointInTime));
Where(e => e is object)
的意义何在?你知道e
是IDateTimeFilter
所以它必须是object
。
@NetMage:查询!= null
的半现代方式。 C# 的问题是 != null
和 == null
比较仍然由任何相应的运算符重载处理,然后可以确定给定对象对它们来说足够空并且等于 null
并返回 true
即使非空-reference 被传入(反之亦然)。可以肯定的是,总是可以使用Object.ReferenceEquals
,但这有点笨拙。现在is object
被is not null
取代(当然很多程序员还不能使用最新的C# 版本,为什么我使用的是旧语法)。
有趣 - 我认为不需要测试。以上是关于可以使用 DateTime 列表过滤 List<object> 的 Linq 查询的主要内容,如果未能解决你的问题,请参考以下文章