2017-01-24 1 views
2

c를 여러 열을 사용하여 세 개의리스트에 가입 :내가이 목록을 가지고 #의 LINQ 람다

var subjects = new List<SubjectModel> 
     { 
      new SubjectModel { subjId = 1, subjName = "Math" }, 
      new SubjectModel { subjId = 2, subjName = "Science" }, 
      new SubjectModel { subjId = 3, subjName = "History" }, 
      new SubjectModel { subjId = 4, subjName = "Language" } 
     }; 

var quizzes = new List<QuizModel> 
     { 
      new QuizModel { quizId = 1, quizDate = DateTime.Parse("2016-11-25"), quizScore = 10, subjectId = 1 }, 
      new QuizModel { quizId = 2, quizDate = DateTime.Parse("2016-11-25"), quizScore = 15, subjectId = 1 }, 
      new QuizModel { quizId = 3, quizDate = DateTime.Parse("2016-11-25"), quizScore = 8, subjectId = 2 }, 
      new QuizModel { quizId = 4, quizDate = DateTime.Parse("2016-11-26"), quizScore = 13, subjectId = 1 }, 
      new QuizModel { quizId = 5, quizDate = DateTime.Parse("2016-11-26"), quizScore = 20, subjectId = 2 } 
     }; 

var exams = new List<ExamModel> 
     { 
      new ExamModel { examId = 1, examDate = DateTime.Parse("2016-11-25"), examScore = 90, subjectId = 1 }, 
      new ExamModel { examId = 2, examDate = DateTime.Parse("2016-11-25"), examScore = 88, subjectId = 2 }, 
      new ExamModel { examId = 3, examDate = DateTime.Parse("2016-11-25"), examScore = 92, subjectId = 4 }, 
      new ExamModel { examId = , examDate = DateTime.Parse("2016-11-26"), examScore = 84, subjectId = 1 }, 

     }; 

var exercises = new List<ExerciseModel> 
     { 
      new ExerciseModel { exerciseId = 1, exerciseDate = DateTime.Parse("2016-11-25"), exerciseScore = 17, subjectId = 1 }, 
      new ExerciseModel { exerciseId = 2, exerciseDate = DateTime.Parse("2016-11-25"), exerciseScore = 15, subjectId = 2 }, 
      new ExerciseModel { exerciseId = 3, exerciseDate = DateTime.Parse("2016-11-26"), exerciseScore = 15, subjectId = 1 }, 
      new ExerciseModel { exerciseId = 4, exerciseDate = DateTime.Parse("2016-11-26"), exerciseScore = 12, subjectId = 4 }, 
      new ExerciseModel { exerciseId = 5, exerciseDate = DateTime.Parse("2016-11-26"), exerciseScore = 10, subjectId = 1 }, 
     }; 

내가 날짜 및 제목별로 각각 성공적으로 그룹에 수 있었다.

var allQuizzes = quizzes.GroupBy(qz => qz.quizDate, (q, values) => 
      new 
      { 
       Date = q, 
       Quizzes = values.GroupBy(v => v.subjectId, (c, values2) => 
        new { 
         SubjectId = c, 
         QuizSum = values2.Sum(v2 => v2.quizScore) 
        }) 
      }); 

var allExercises = exercises.GroupBy(ex => ex.exerciseDate, (e, values) => 
      new { 
       Date = e, 
       Exercises = values.GroupBy(x => x.subjectId, (z, values2) => 
        new { 
         SubjectId = z, 
         ExerSum = values2.Sum(r => r.exerciseScore) 
        }) 
      }); 

var allExams = exams.GroupBy(ex => ex.examDate, (e, values) => 
      new 
      { 
       Date = e, 
       Exercises = values.GroupBy(x => x.subjectId, (z, values2) => 
        new 
        { 
         SubjectId = z, 
         ExamSum = values2.Sum(r => r.examScore) 
        }) 
      }); 

그러나 모든 점수의 합계를 얻으려면이 세 가지를 모두 가입해야합니다. 최종 테이블은 이와 같이 표시되어야합니다.

----------------------------------------------------------------- 
|  Date  | Math | Science | History | Language | 
| 11/25/2016 | 132 |  111 |   0 |  92 | 
| 11/26/2016 | 122 |  20 |   0 |  12 | 
----------------------------------------------------------------- 

나는 그들과 합류하려고 시도했지만 여러 열로 합류 할 수 없었다.

+0

피봇을 찾아야합니다 –

+0

@ irenebelserion1 답변이 도움이된다면 도움이됩니까? :) –

답변

1

3 개의 콜렉션 결과 모두 동일한 익명 클래스 (동일한 아이디어가 Andrei가 첫 번째 대답에 포함됨) 형태로 선택하여 매핑 및 변환없이 모든 목록에서 모든 결과를 수집 할 수 있습니다.

var allQuiz = quizzes.GroupBy(x => new { x.subjectId, x.quizDate }) 
        .Select(x => new { 
          Date = x.Key.quizDate, 
          Subj = x.Key.subjectId, 
          Sum = x.Sum(r=>r.quizScore)}); 

var allExam= exams.GroupBy(x => new { x.subjectId, x.examDate }) 
        .Select(x => new { 
          Date = x.Key.examDate, 
          Subj = x.Key.subjectId, 
          Sum = x.Sum(r=>r.examScore)}); 

var allExc = exercises.GroupBy(x => new { x.subjectId, x.exerciseDate }) 
        .Select(x => new { 
          Date = x.Key.exerciseDate, 
          Subj = x.Key.subjectId, 
          Sum = x.Sum(r=>r.exerciseScore)}); 

함께 모든 결과의 결합 :

var all = allQuiz.ToList(); 
all.AddRange(allExam.ToList()); 
all.AddRange(allExc.ToList()); 

var result = all.GroupBy(x => new { x.Date, x.Subj }) 
       .Select(x => new { x.Key.Date, x.Key.Subj, Sum = x.Sum(s => s.Sum)}); 

var list = result.GroupBy(r => r.Date).Select(x => new { 
     Date = x.Key, 
     Math = x.SingleOrDefault(t=>t.Subj==1)?.Sum ?? 0, 
     Science = x.SingleOrDefault(t=>t.Subj==2)?.Sum ?? 0, 
     History = x.SingleOrDefault(t=>t.Subj==3)?.Sum ?? 0, 
     Language = x.SingleOrDefault(t=>t.Subj==4)?.Sum ?? 0, 
     }); 

출력을 LinqPad에 :

enter image description here

+0

예, 여기 있습니다. 고마워. 몇 줄을 수정했는데, SingleorDefault() 부분에서 오류가 계속 발생합니다. – irenebelserion1

+0

@ irenebelserion1 감사합니다. 나는 upvote도 thankfull 것입니다 :) –

0

다음은 아이디어입니다. 그룹화하는 동안 구별을 유지하는 대신 세 가지를 모두 같은 구조로 변환 할 수 있습니다. 예 :

var allQuizzes = quizzes.GroupBy(qz => qz.quizDate, (q, values) => 
     new 
     { 
      Date = q, 
      Results = values.GroupBy(v => v.subjectId, (c, values2) => 
       new { 
        SubjectId = c, 
        Sum = values2.Sum(v2 => v2.quizScore) 
       }) 
     }); 

알림 이름 "결과"와 "합계"는 다른 두 개체에도 동일하게 사용할 수 있습니다. 에 의해 날짜에 의해 그 안에

{ 
    Date: 
    Results: [ 
     {SubjectId, Sum} 
     {SubjectId, Sum} 
     ... 
    ] 
} 

그들은 지금 모두 동일하기 때문에, 당신은 다르게 치료를 중지 할 수 있습니다, 사용 UNION이 세 가지 병합, 그룹을 : 그리고 지금 당신은 3 개 개의 모음을, 같은 구조의 모든가 제목. 그렇다면 주제 목록을 반복하여 필요한 정보를 얻을 수 있으며 "최종 표"가 무엇을 의미하는지에 따라 달라질 수 있습니다.

0

이 내가 생각 해낸 것입니다. 최적으로 최적화되지 않았지만 충분할 수도 있습니다. 결과를 StringBuilder로 렌더링했습니다.

public enum TestType 
{ 
    Quiz, 
    Exam, 
    Exercise, 
} 

public class TestScore 
{ 
    public TestType Type { get; set; } 
    public DateTime Date { get; set; } 
    public int  Score { get; set; } 
    public int  SubjectId { get; set; } 

    // Constructors - make a TestScore object 

    public TestScore(QuizModel q) 
    { 
     Type  = TestType.Quiz; 
     Date  = q.quizDate; 
     Score  = q.quizScore; 
     SubjectId = q.SubjectId;    
    } 

    public TestScore(ExamModel e) 
    { 
     Type  = TestType.Exam; 
     Date  = e.examDate; 
     Score  = e.examScore; 
     SubjectId = e.SubjectId;    
    } 

    public TestScore(ExerciseModel e) 
    { 
     Type  = TestType.Exercise; 
     Date  = e.exerciseDate; 
     Score  = e.exerciseScore; 
     SubjectId = e.SubjectId;    
    } 
} 

TestScore로 변환 :

List<TestScore> scores = new List<TestScore>(); 

scores.AddRange(quizzes.Select(q => new TestScore(q)); 
scores.AddRange(exams.Select(e => new TestScore(e)); 
scores.AddRange(exercises.Select(e => new TestScore(e)); 

을 이제 하나의 데이터 소스 대신에 세 가지가

var result = 
quizzes.Select(q => new {SubjectId = q.subjectId, Date = q.quizDate, Score = q.quizScore}) 
    .Union(exams.Select(e => new {SubjectId = e.subjectId, Date = e.examDate, Score = e.examScore})) 
    .Union(exercises.Select(e => new {SubjectId = e.subjectId, Date = e.exerciseDate, Score = e.exerciseScore})) 
    .GroupBy(arg => arg.Date, 
    (key, values)=> 
    new 
    { 
     Key = key, 
     Scores = values.GroupBy(v => v.SubjectId, (s, values2) => new { SubjectId = s, SumScore = values2.Sum(v2 => v2.Score) }) 
    }); 

StringBuilder sb = new StringBuilder("Date\t\t"); 
foreach (SubjectModel subject in subjects) 
{ 
    sb.Append($"{subject.subjName}\t"); 
} 

sb.AppendLine(); 

foreach (var record in result) 
{ 
    sb.Append($"{record.Key.ToShortDateString()}\t"); 
    foreach (SubjectModel subject in subjects) 
    { 
     int sum = record.Scores.Where(s => s.SubjectId == subject.subjId).Select(s => s.SumScore).DefaultIfEmpty(0).Single(); 
     sb.Append($"{sum}\t"); 
    } 
    sb.AppendLine(); 
} 

string finalTable = sb.ToString(); 
0

대신 결과를 유지하기 위해 세 가지 다른 익명의 객체를 사용하는 자신의 클래스를 만들 결과를 쉽게 표시 할 수 있습니다.