У меня есть список объектов ViewsHistory, отсортированных по UtcNow:
var views = List<ViewHistory>
Класс ViewHistory:
public class ViewHistory
{
[PrimaryKey]
public string YYMMDD { get; set; }
public int UtcNow { get; set; }
public int Learn { get; set; }
public int Practice { get; set; }
public int Quiz { get; set; }
}
Есть ли способ с помощью LINQ создать новый список, суммирующий итоги обучения, практики и викторины по ГГММ?
Вы можете добиться этого с помощью выражения GroupBy
LINQ:
var views = new List<ViewHistory>();
views.Add(new ViewHistory {YYMMDD = "190530", Learn = 20, Practice = 1, Quiz = 30});
views.Add(new ViewHistory { YYMMDD = "190531", Learn = 1, Practice = 1, Quiz = 30 });
views.Add(new ViewHistory { YYMMDD = "190529", Learn = 2, Practice = 1, Quiz = 30 });
views.Add(new ViewHistory { YYMMDD = "190410", Learn = 2, Practice = 1, Quiz = 30 });
var newViews = views.GroupBy(t => t.YYMMDD.Substring(0, 4))
.Select(t => new
{
yymm = t.Key,
learnSum = t.Select(f => f.Learn).Sum(),
practiceSum = t.Select(f => f.Practice).Sum(),
quizSum = t.Select(f => f.Quiz).Sum()
}).ToList();
Результат
{ yymm = "1905", learnSum = 23, practiceSum = 3, quizSum = 90 },
{ yymm = "1904", learnSum = 2, practiceSum = 1, quizSum = 30 }
обратите внимание на YYMM
в ОП, это может иметь или не иметь отношение к делу или опечатка
var views = new List<ViewHistory>
{
new ViewHistory {YYMMDD = "190515", Learn = 1, Practice = 2, Quiz = 3},
new ViewHistory {YYMMDD = "190514", Learn = 5, Practice = 6, Quiz = 7},
new ViewHistory {YYMMDD = "190415", Learn = 100, Practice = 110, Quiz = 120},
new ViewHistory {YYMMDD = "190414", Learn = 150, Practice = 160, Quiz = 170}
};
var monthlyTotals = views.GroupBy(
v => v.YYMMDD.Substring(0, 4),
v => v,
(yearMonth, groupedViews) =>
new
{
YearMonth = yearMonth,
LearnSum = groupedViews.Sum(view => view.Learn),
PracticeSum = groupedViews.Sum(view => view.Practice),
QuizSum = groupedViews.Sum(view => view.Quiz)
}).ToList();
monthlyTotals
(скопировано из окна Visual Studio Locals во время отладки)
monthlyTotals Count = 2 System.Collections.Generic.List<<>f__AnonymousType0<string, int, int, int>>
[0] { YearMonth = "1905", LearnSum = 6, PracticeSum = 8, QuizSum = 10 } <Anonymous Type>
[1] { YearMonth = "1904", LearnSum = 250, PracticeSum = 270, QuizSum = 290 } <Anonymous Type>
И, конечно же, если вы предпочитаете не использовать анонимный тип, вы можете определить новый класс (скажем, MonthlyViewTotals
, например) и создать экземпляр списка для вашего monthlyTotals
вместо этого:
var monthlyTotals = views.GroupBy(
v => v.YYMMDD.Substring(0, 4),
v => v,
(yearMonth, groupedViews) =>
new MonthlyViewTotals // <-- no more anonymous types
{
YearMonth = yearMonth,
LearnSum = groupedViews.Sum(view => view.Learn),
PracticeSum = groupedViews.Sum(view => view.Practice),
QuizSum = groupedViews.Sum(view => view.Quiz)
}).ToList();
Это выглядит довольно устаревшим, почему вы сохраняете его как строку? Также смотрите
String.Substring