Попытка свернуть данные с помощью linq

У меня следующая структура классов:

 public class TaskLog
 {
    public DateTime LogDate { get; set; }
    public string Robot { get; set; }
    public string Task { get; set; }
    public Enums.ProbeDataState State { get; set; }

    public TaskLog()
    {
    }
}

Я создал общий список следующим образом:

List<TaskLog> Logs;

Мой вывод:

Robot   Date                    State
---------------------------------------------
aaa     8/5/2013 12:00:00 AM    Task:1=fileDeltaFailed
aaa     8/5/2013 12:00:00 AM    Task:2=fileDeltaFailed
aaa     8/5/2013 12:00:00 AM    Task:4=fileDeltaFailed
bbb     8/5/2013 12:00:00 AM    Task:1=fileDeltaFailed
bbb     8/5/2013 12:00:00 AM    Task:2=fileDeltaFailed
bbb     8/5/2013 12:00:00 AM    Task:4=fileDeltaFailed

Однако я хотел бы сгруппировать задачи и сформулировать следующее:

                                Tasks
Robot   Date                    1                 2                4
aaa     8/5/2013 12:00:00 AM    fileDeltaFailed   fileDeltaFailed  fileDeltaFailed 
bbb     8/5/2013 12:00:00 AM    fileDeltaFailed   fileDeltaFailed  fileDeltaFailed

Я безуспешно пытался использовать groupby и застрял.

e.g.

 var dataQuery = Logs.Where(w => w.LogDate >= start && w.LogDate <= finish).GroupBy(g => g.LogDate).Select(t => new
            {
                LogDate = t.Key,
                Details = t.OrderBy(o => o.Robot)
            }).ToList();

person Pete Dragun    schedule 14.08.2013    source источник
comment
Похоже, вы хотите сделать что-то похожее на stackoverflow.com/q/7325278/2460812   -  person brader24    schedule 14.08.2013
comment
@ brader24 Сводная таблица радикально отличается от группы по.   -  person Servy    schedule 14.08.2013
comment
Итак, вы хотите поменять задачи? Каждый такс должен быть столбиком?   -  person Tim Schmelter    schedule 14.08.2013
comment
pivot и groupby - это не одно и то же   -  person Roar    schedule 14.08.2013
comment
@TimSchmelter, да, каждая задача должна быть столбцом.   -  person Pete Dragun    schedule 14.08.2013
comment
У каждого робота будет одинаковое количество задач.   -  person Pete Dragun    schedule 14.08.2013
comment
Какова корреляция между роботом и задачей? Может быть ни один, ни один или один, ни один ко многим?   -  person gunr2171    schedule 14.08.2013
comment
Я понимаю, что создание вывода сложнее, чем просто создание группы по. Я подозреваю, что это часть возможного решения, как, казалось, предполагал Пит. Это также возможный дубликат stackoverflow.com/q/963491/2460812   -  person brader24    schedule 14.08.2013


Ответы (3)


Если я понимаю вопрос, вам нужно сопоставление задачи с состоянием для каждого робота. Вы можете сгруппировать по роботам и выбрать словарь для каждой группы:

Logs.GroupBy(t => t.Robot).Select(g => new {
    Robot = g.Key,
    TaskStates = g.ToDictionary(t => t.Task, t => t.State)
})

Это предполагает, что имена задач уникальны для каждого робота (в противном случае ToDictionary вызовет исключение).

Вы также можете добавить еще один уровень группировки дат:

Logs.GroupBy(t => t.LogDate).Select(g => new {
    Date = g.Key,
    Details = g.GroupBy(t => t.Robot).Select(g => new {
        Robot = g.Key,
        TaskStates = g.ToDictionary(t => t.Task, t => t.State)
    }).ToList()
})

Обратите внимание, что свойство Details по сути эквивалентно моему первому примеру, с той лишь разницей, что оно запрашивает внешнюю группировку, а не всю последовательность. Результатом является последовательность {Date, Details}, где каждая "деталь" представляет собой список {Robot, TaskStates}.

Я не тестировал это, поэтому дайте мне знать, если есть какие-то ошибки, которые я пропустил.

person nmclean    schedule 14.08.2013
comment
Ваш пример - именно то, что мне нужно! Я смог добиться желаемых результатов. - person Pete Dragun; 20.08.2013

var result = Logs.GroupBy(x=> new {x.Robot, x.Date})                     
                 .Select(g=> {
                               var a = g.ToList();
                               return
                               new {
                                 a[0].Robot,
                                 a[0].Date,
                                 Task1 = a[0].State,
                                 Task2 = a[1].State,
                                 Task4 = a[2].State
                               };
                             });

Предположим, вам нужно определить фиксированное число Tasks, и, чтобы сделать его более безопасным, мы можем сделать что-то вроде этого:

var result = Logs.GroupBy(x=> new {x.Robot, x.Date})
                 .Select(g=> { 
                               var c = g.Count();
                               var a = g.ToList();
                               return 
                               new {
                                    a[0].Robot,
                                    a[0].Date,
                                    Task1 = a[0].State,
                                    Task2 = c > 1 ? a[1].State : "",
                                    Task4 = c > 2 ? a[2].State : ""
                                   };
                             });
person King King    schedule 14.08.2013

попробуй это:

var newData = from w in Logs
              where w.LogDate >= start && w.LogDate <= finish
              group w by w.LogDate into g
              select new 
              {
                  LogDate = g.Key,
                  Details = g.ToList().OrderBy(o => o.Robot)
              };

Запрос newData содержит список объектов с LogDate и Detais (Список задач, упорядоченных роботом).

person Julio Borges    schedule 14.08.2013
comment
Кто-то опубликовал другое решение, и мне удалось его использовать, прежде чем они его удалили :( - person Pete Dragun; 14.08.2013
comment
Если у вас будет несколько дат для одного робота, вам нужно будет сгруппировать их как по роботу, так и по дате. В этом вопросе показано, как это сделать: stackoverflow.com/q/847066/2460812 - person brader24; 14.08.2013
comment
Пожалуйста, @PeteDragun, закройте вопрос - person Julio Borges; 14.08.2013
comment
@JulioBorges, зачем удалять вопрос? - person King King; 14.08.2013