【问题标题】:How to filter list that has date and retrieve only data within 7 days如何过滤具有日期的列表并仅检索 7 天内的数据
【发布时间】:2018-06-22 17:35:05
【问题描述】:

所以我有这个模型:

Student Model

public int StudentId {get; set;}
public string StudentName {get; set;}
public DateTime EnrollDate {get; set;}

我还有一个学生模型列表,类似于

List<Student> listOfStudents = new List<Student>();

在该列表中,有 100 名学生的详细信息和注册日期。

我接下来要做的是将列表排序为从最新的到最旧的显示。

listOfStudents.Sort((x, y) => DateTime.Compare(y.EnrollDate, x.EnrollDate));

它正在工作。但是,我目前正在努力在从今天起 7 天内仅显示 EnrollDate。

【问题讨论】:

  • 您有学生的 EnrollDate 比今天大吗?您是否还想要今天之前和之后但在 7 天限制内的学生?
  • 您好,感谢今天。今天之前,但在 7 天内限制。谢谢!
  • 你能写一个函数,它接受一个单个日期,如果满足你的条件则返回true,否则返回false?

标签: c# asp.net linq lambda


【解决方案1】:

从概念上讲,我认为 LINQ 很像 SQL。你有SELECT 部分,这是你的投影(即我从这组数据中提取了什么?)。如果您从 LINQ 中省略 Select() 子句,您将获得整个记录,而如果您只想提取其中的一部分,您将获得整个记录。您有 WHERE 部分,它是一个限制器或过滤条件,当应用于集合时,它只会拉回满足所述条件的记录。最后,您可以应用一些操作来影响返回集的顺序。这就是OrderBy()OrderByDescending() 发挥作用的地方。因此,让我们将这些概念映射到下面的示例


没有Select(),但我们有Where()OrderBy()

var then = DateTime.Now.AddDays(-7); //One portion of our Where. More below
var sortedStudents = listOfStudents
  //Our predicate. 's' = the Student passed to the function. Give me only the students
  //where s.EnrollDate is greater or equal to the variable 'then' (defined above)
  .Where(s => s.EnrollDate >= then) 
  //We have no Select statement, so return whole students
  //And order them by their enrollment date in ascending order
  .OrderBy(s => s.EnrollDate);

运行时,sortedStudents 将加载符合我们Where() 标准的学生(整个Student 对象,而不是投影)。 Where() 函数采用指定条件的谓词。谓词只是一个函数,它接受我们正在过滤的集合中的一条记录,并返回一个bool 指示是否应该包含它。


让我们通过调整Where()来更改过滤器

//Notice we've changed 'then' from 7 days ago to a fixed point in time: 26 June 2018
var then = new DateTime.Parse("26 June 2018"); 
var sortedStudents = listOfStudents
  .Where(s => s.EnrollDate >= then) 
  //Still no Select(). We'll do that next
  .OrderBy(s => s.EnrollDate);

就像之前sortedStudents 将拥有完整的Student 记录一样,但这次它将仅包含那些在之后 2018 年 6 月 26 日注册的记录,具体如下:我们的谓词。


让我们添加一个Select()

var then = new DateTime.Parse("26 June 2018"); 
var dates = listOfStudents
  .Where(s => s.EnrollDate >= then) 
  .Select(s => s.EnrollDate);

现在我们已经对其进行了更改,以便我们只提取EnrollDate 而不是拉回一个整个 Student。请注意,我已将接收变量的名称从 sortedStudents 更改为 dates,这反映了它现在只包含 DateTime 对象列表的事实。


您仍然可以将 .OrderBy() 替换为 .OrderByDescending() 以更改顺序。

【讨论】:

  • 感谢您的帮助!
  • 非常感谢您的帮助。我还有一个要求。如何修改/排序删除所有小于“2018 年 6 月 26 日”的列表的列表?因此,该列表的数据日期将仅大于 2018 年 6 月 26 日。任何日期在 6 月 26 日之前的数据都将被删除
  • 所以你必须像在编写 SQL 一样思考(不确定你是否已经这样做了)。每当您过滤一个集合时,您都会在WHERE 子句中执行此操作。我会用其他信息更新我的答案。
【解决方案2】:

如何将问题分解为 2 个子问题?

子问题 #1

仅显示从今天起 7 天内的 EnrollDate

我们只需要Students 的EnrollDate 属性在从今天起的7 天内:

var today = DateTime.UtcNow;
sevenDaysOldList = listOfStudents.Where(x => (today - x.EnrollDate).TotalDays < 7); 

两个日期相减得到带有TotalDays 属性的TimeSpan,我们可以使用它来确定两个日期之间经过的天数。

子问题 #2

按从最新到最旧的顺序排列列表。

我们需要将sevenDaysOldListEnrollDate 降序排列:

sevenDaysOldList.Sort((x, y) => y.EnrollDate.CompareTo(x.EnrollDate));

..这将对列表进行适当的排序。 OrderByDescending 是一个很好的候选者(它返回一个实现 IOrderedEnumerable&lt;T&gt; 的新有序列表):

sevenDaysOldList.OrderByDescending(x => x.EnrollDate);
// and of course .OrderBy(x => x.EnrollDate) for ascending order

结合 #1 和 #2

您现在可以将两个子问题的解决方案合二为一。你如何做是由你自己决定的。我会这样做:

var sevenDaysOldList = listOfStudents.Where(x => (today - x.EnrollDate).TotalDays < 7)
                                     .OrderByDescending(x => x.EnrollDate);

更新:评论中的问题

如何修改/排序删除所有小于“2018 年 6 月 26 日”的列表的列表?因此,该列表将仅包含大于 2018 年 6 月 26 日的数据日期。任何日期在 6 月 26 日之前的数据都将被删除

您可以在DateTime 变量中初始化该日期,并将其与List&lt;T&gt;.RemoveAll(Predicate&lt;T&gt;) 一起使用,以删除sevenDaysOldList 中小于该日期的项目:

var filterDate = new DateTime(2018, 06, 26);
sevenDaysOldList.RemoveAll(x => x.EnrollDate < filterDate);

【讨论】:

  • 非常感谢您的帮助。我还有一个要求。如何修改/排序删除所有小于“2018 年 6 月 26 日”的列表的列表?因此,该列表的数据日期将仅大于 2018 年 6 月 26 日。任何日期在 6 月 26 日之前的数据都将被删除
  • 您好!抱歉再次打扰。嗯,如果删除 2018 年 6 月 26 日之后的所有日期怎么办?
  • 当然这很容易弄清楚.. 将x.EnrollDate &lt; filterDate 切换为x.EnrollDate &gt; filterDate :)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多