Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/linq/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 按日期范围分组,每个组内的计数和排序LINQ_C#_Linq - Fatal编程技术网

C# 按日期范围分组,每个组内的计数和排序LINQ

C# 按日期范围分组,每个组内的计数和排序LINQ,c#,linq,C#,Linq,我的对象中存储了一组日期。这是示例数据。实时的日期将来自服务电话,我不知道返回的日期和数量: var ListHeader = new List<ListHeaderData> { new ListHeaderData { EntryDate = new DateTime(2013, 8, 26) }, new ListHea

我的对象中存储了一组日期。这是示例数据。实时的日期将来自服务电话,我不知道返回的日期和数量:

        var ListHeader = new List<ListHeaderData>
        {
            new ListHeaderData
            {
                EntryDate = new DateTime(2013, 8, 26)
            },
            new ListHeaderData
            {
                EntryDate = new DateTime(2013, 9, 11)
            },
            new ListHeaderData
            {
                EntryDate = new DateTime(2013, 1, 1)
            },
            new ListHeaderData
            {
                EntryDate = new DateTime(2013, 9, 15)
            },
            new ListHeaderData
            {
                EntryDate = new DateTime(2013, 9, 17)
            },
            new ListHeaderData
            {
                EntryDate = new DateTime(2013, 9, 5)
            },
        };
这是按日期分组的,所以我有6个组,每个组有一个日期。如何按日期范围分组、在每个组中计数和排序?提前感谢。

这样做怎么样

为分组和分组引入一个新属性

class ListHeaderData
{
    public DateTime EntryDate;
    public int DateDifferenceFromToday
    {
        get
        {
            TimeSpan difference = DateTime.Today - EntryDate.Date;
            if (difference.TotalDays == 0)//today
            {
                return 1;
            }
            else if (difference.TotalDays <= 14)//less than 2 weeks
            {
                return 2;
            }
            else
            {
                return 3;//something else
            }
        }
    }
}
像这样使用它

class ListHeaderData
{
    public DateTime EntryDate;
    public DateRange DateDifferenceFromToday
    {
        get
        {
            //I think for this version no comments needed names are self explanatory
            TimeSpan difference = DateTime.Today - EntryDate.Date;
            if (difference.TotalDays == 0)
            {
                return DateRange.Today;
            }
            else if (difference.TotalDays <= 14)
            {
                return DateRange.LessThanTwoWeeks;
            }
            else
            {
                return DateRange.MoreThanTwoWeeks;
            }
        }
    }
}

enum DateRange
{ 
    None = 0,
    Today = 1,
    LessThanTwoWeeks = 2,
    MoreThanTwoWeeks = 3
}
 var defaultGroups = from l in ListHeader
     group l by l.DateDifferenceFromToday into g // <--Note group by DateDifferenceFromToday
     orderby g.Min(x => x.EntryDate)
     select new { GroupBy = g };
var defaultGroups=来自ListHeader中的l
按l.Date将l分组(从今天到g//x.EntryDate)
选择新的{GroupBy=g};

您是否特别希望以这种方式实现解决方案?另外,您真的想在类中引入虚假属性来满足这些要求吗

这三条线将满足您的要求,对于大型集合,性能将更高

var todays = listHeader.Where(item => item.EntryDate == DateTime.Today);

var twoWeeks = listHeader.Where(item => item.EntryDate < DateTime.Today.AddDays(-1) 
                                && item.EntryDate >= DateTime.Today.AddDays(-14));

var later = listHeader.Where(item => item.EntryDate < DateTime.Today.AddDays(-14));
请注意,我正在通过Linq Select和匿名类添加分组,以便再次动态推送组属性,而不影响原始类。这将基于原始post生成以下输出:

Group EntryDate Today 17/09/2013 00:00:00 LessThanTwoWeeks 11/09/2013 00:00:00 LessThanTwoWeeks 15/09/2013 00:00:00 LessThanTwoWeeks 05/09/2013 00:00:00 MoreThanTwoWeeks 26/08/2013 00:00:00 MoreThanTwoWeeks 01/01/2013 00:00:00 输出为:

Group Count Today 1 LessThanTwoWeeks 3 MoreThanTwoWeeks 2 组计数 今天1 第三周
两周以上2介绍数组,其中包含要分组的范围。这里有两个范围-今天(零天)和14天(两周):

更新:添加用于分组的自定义范围:

var ranges = new List<int?>();
ranges.Add(0); // today
ranges.Add(7*2); // two weeks
ranges.Add(DateTime.Today.Day); // within current month
ranges.Add(DateTime.Today.DayOfYear); // within current year
ranges.Sort();
var ranges=新列表();
范围。添加(0);//今天
范围。添加(7*2);//两周
ranges.Add(DateTime.Today.Day);//当月内
ranges.Add(DateTime.Today.DayOfYear);//本年度内
ranges.Sort();

我想这取决于您计划使用此功能的程度。我有很多报告要生成,所以我创建了一个模型
IncrementDateRange
,其中包含
StartTime
EndTime
TimeIncrement
,作为枚举

时间增量处理程序有许多基于开关的函数,可以根据小时/天/周/月/季度/年等显示开始和结束范围之间的时间列表

然后,您将得到
IncrementDateRange
的列表,并且在linq中类似于:

TotalsList = times.Select(t => new RetailSalesTotalsListItem()
{
    IncrementDateRange = t,
    Total = storeSales.Where(s => s.DatePlaced >= t.StartTime && s.DatePlaced <= t.EndTime).Sum(s => s.Subtotal),
})

@JimBallard刚看到你的个人资料。OMG 30年以上的软件经验?我还没有过30岁!哈我的第一个代码是输入IBM360的穿孔卡。360是全新的和最前沿的!我会避免为此使用
int
;代码的读者将不知道它的意思。为此使用类似于
enum
的东西;这对计算机来说都是一样的,但它的可读性要高得多。此外,没有理由创建一个新的匿名类型只是为了将组放入其中。如果您只需要该组,只需选择该组。@Servy yes这里的匿名类型是多余的,我只是复制了OP的代码。我会考虑EnUM在我的answer@Servy使用枚举更新。我希望现在它看起来更容易阅读。根据OP的评论,天的分组似乎不完全在固定的天数内,即他提到了上个月,这是一个可变的天数。@谢谢,我还没有看到OP对其他答案的评论。让我检查一下。@Servy我认为用OP需要的任何值填充范围列表没有任何问题。例如,对于currentMonth,您应该在列表中添加
DateTime.Day.Day
。另外,如果不知道将添加哪些范围,那么在查询之前应该对范围列表进行排序。@lazyberezovsky-我非常喜欢这种方法,但是如何对单个组进行asc/desc排序?@lazyberezovsky-这正是我想要的。非常感谢您的回复。如何按组排序?
var ord = todays.Select(item => new {Group = DateRange.Today, Count=todays.Count()})
          .Union(
          twoWeeks.Select(item => new {Group = DateRange.LessThanTwoWeeks, Count=twoWeeks.Count()}))
          .Union(
          later.Select(item => new {Group = DateRange.MoreThanTwoWeeks, Count=later.Count()}))
          .OrderBy(item => item.Group);
Group Count Today 1 LessThanTwoWeeks 3 MoreThanTwoWeeks 2
var today = DateTime.Today;
var ranges = new List<int?> { 0, 14 };
var defaultGroups = 
      from h in ListHeader
      let daysFromToday = (int)(today - h.EntryDate).TotalDays
      group h by ranges.FirstOrDefault(range => daysFromToday <= range) into g
      orderby g.Min(x => x.EntryDate)
      select g;
var ranges = new List<int?>();
ranges.Add(0); // today
ranges.Add(7*2); // two weeks
ranges.Add(DateTime.Today.Day); // within current month
ranges.Add(DateTime.Today.DayOfYear); // within current year
ranges.Sort();
TotalsList = times.Select(t => new RetailSalesTotalsListItem()
{
    IncrementDateRange = t,
    Total = storeSales.Where(s => s.DatePlaced >= t.StartTime && s.DatePlaced <= t.EndTime).Sum(s => s.Subtotal),
})
TotalsList = storeSales.GroupBy(g => g.IncrementDateRange.StartTime).Select(gg => new RetailSalesTotalsListItem()
{
    IncrementDateRange = times.First(t => t.StartTime == gg.Key),
    Total = gg.Sum(rs => rs.Subtotal),
}).ToList(),