【问题标题】:Is it possible, and how to refactor this with lambda linq是否有可能,以及如何用 lambda linq 重构它
【发布时间】:2018-08-29 03:51:56
【问题描述】:

我正在尝试确定一个名称是否在 WorkedDataPoint 列表中并且落在 totalDaysInDateRange 中的任何一天的方法。基本前提是,如果这两个日期匹配,则该人当天工作 - 我正在尝试计算“工作”天数。每个用户每天也可能有不止一个条目,我们只能数一个,一天一个,所以“morelinq”中的 DistinctBy 似乎是一个不错的选择...

我在这里应该可以正常工作,编译器在工作,所以不能肯定地说。但是我将如何使用 linq lambda 表达式来使其更简洁 - 特别是 foreach 循环,可以在这个应用程序中的 lambda 中以某种方式吗?

    public class WorkedDatapoint
    {
        public string AssignerName { get; set; }
        public DateTime Date { get; set; }
        public bool AssignedToOther { get; set; }
    }
    List<DateTime> totalDaysInDateRange
    List<WorkedDataPoint> AssignersList
    testtech = "Bobby"

    //The two lists are loaded here

    int totalDaysWorked = 0;
    foreach (var day in totalDaysInDateRange)
    {
        if (AssignersList.Where(d => testtech.Contains(d.AssignerName)).DistinctBy(d => d.Date.Date).Any(d => d.Date.Date == day.Date)
        {
            totalDaysWorked++;      
        }
    }

编辑:我想我知道了,但明天才能测试。有什么方法可以内联声明该变量 TotalDaysWorked 还是要求太多?

          int totalDaysWorked = 0;
          totalDaysInDateRange.ForEach((day) =>
          {
              if (AssignersList
                .Where(d => testtech.Contains(d.AssignerName))
                .DistinctBy(d => d.Date.Date)
                .Any(d => d.Date.Date == day.Date))
          { totalDaysWorked++; }});

这种方法会“处理”数千条记录,因此对于速度优化(大量 RAM 和 Intel-I7)的想法也将不胜感激。

【问题讨论】:

  • 让事情更“流畅”并不总是一件好事——它并不总是能提高可读性,而且通常会使调试变得更加困难,因为你不能轻易地停在不同的步骤上。至于性能,你也许可以做一个并行的foreach

标签: c# linq lambda refactoring


【解决方案1】:

可以这样做:

int totalDaysWorked = totalDaysInDateRange.Intersect(AssignersList.Select(b => b.Date)).Count();

As except 在内部使用 Set:

int count = totalDaysInDateRange.Count() - totalDaysInDateRange.Except(AssignersList.Select(b => b.Date)).Count();

警告: 对于大量数字,linq 非常慢,应该被禁止。更多关于这个here

【讨论】:

    【解决方案2】:

    我建议在 Date 加入 totalDaysInDateRange 和 AssignersList。然后按 AssignerName 和 Date 分组。你会得到日期

    var jointList = totalDaysInDateRange.Join(
                            AssignersList,
                            p => p,
                            c => c.Date,
                            (p, c) => new { c.AssignerName, c.Date }
                        ).Distinct().GroupBy(x => x.AssignerName).Select(group => 
                            new { 
                                 AssignerName = group.Key, 
                                 Count = group.Count() 
                            }).ToList();
    

    【讨论】:

      【解决方案3】:

      您可以为您的问题编写 linq 查询,例如:-

      var AssignerDaysCount = assignerList.Where(filter => 
      totalDaysInDateRange.Contains(filter.Date.Date))
      .GroupBy(item => item.AssignerName)
      .Select(lst => new { AssignerName = lst.Key, DaysCount = lst.Select(cnt   =>   cnt.Date).Distinct().Count() })
      .ToList();
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2017-05-02
        • 2015-02-19
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多