Возможно ли и как это сделать с помощью lambda linq? - PullRequest
0 голосов
/ 29 августа 2018

Я пытаюсь определить способ, где, если имя находится в списке WorkedDataPoint и попадает в любой из дней в totalDaysInDateRange, оно считает его. Основная предпосылка: если эти две даты совпадают, человек работал в тот день - я пытаюсь подсчитать количество «отработанных» дней. Также на одного пользователя может приходиться более одной записи в день, и мы можем считать только одну, одну на день, так что DistinctBy в "morelinq" показался хорошим выбором ...

То, что у меня здесь, должно работать нормально, компилятор на работе, поэтому не могу сказать наверняка. Но как бы я сделал это с помощью лямбда-выражений linq, чтобы сделать его более лаконичным - особенно цикл foreach, может ли это быть в лямбда-выражении в этом приложении как-то?

    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++; }});

Этот метод "хрустит" тысячами записей, поэтому мы очень ценим мысли об оптимизации для скорости (много оперативной памяти и Intel-I7).

Ответы [ 3 ]

0 голосов
/ 29 августа 2018

Вы можете написать запрос 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();
0 голосов
/ 29 августа 2018

Я рекомендую присоединиться к totalDaysInDateRange и AssignersList в Date. Затем сгруппируйте по 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();
0 голосов
/ 29 августа 2018

Можно сделать что-то вроде этого:

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

Как исключение использует Set внутри:

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

Внимание: Для больших чисел linq невероятно медленный и должен быть забанен. Подробнее об этом здесь :

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...