【发布时间】:2018-11-23 07:58:59
【问题描述】:
我试图有条件地显示一个“周列表”(一周中的每一天),要么显示所有 5 天(周一至周五),要么基于单个“列表项”(代表一周中所有天的单个列表项) on 如果每天的所有项目都相同(键除外)。在我将“DayFunctions”(列表)添加为“周列表”的一个项目之前,以下工作。使用 List 属性进行分组时是否需要做一些不同的事情?
我无法在 SO 中找到任何解决此特定分组问题的内容,甚至在谷歌上搜索(好几天)。
使用自定义比较器更新
//POCO
public class ScheduleWeek : IScheduleWeek
{
public int Id { get; set; }
public int Yr { get; set; }
public int WeekNo { get; set; }
public List<ScheduleDay> ScheduleDays { get; set; }
}
// POCO
public class ScheduleDay : IScheduleDay
{
public int Id { get; set; }
public int ScheduleWeekId { get; set; }
public string EmpId { get; set; }
public DateTime ScheduleDayDt { get; set; }
public Shift Shift { get; set; }
public Station Station { get; set; }
public List<DayFunction> DayFunctions { get; set; }
}
// POCO
public class DayFunction
{
public int ScheduleDayId { get; set; }
public int FunctionId { get; set; }
}
// HELPER METHOD
public async Task<List<ScheduleDay>> GetScheduleDaysWithDayFunctions(int stationId,
string empId,
int scheduleWeekId)
{
var sdlist = await _ctx.ScheduleDays
.Where(sd => sd.ScheduleDayDt.DayOfWeek != DayOfWeek.Sunday &&
sd.ScheduleDayDt.DayOfWeek != DayOfWeek.Saturday &&
sd.Station.Id == stationId &&
sd.EmpId == empId &&
sd.ScheduleWeekId == scheduleWeekId)
.Include(d => d.DayFunctions)
.ToListAsync();
return sdlist;
}
// HELPER METHOD
// ** ADDED CUSTOM COMPARER
public class ScheduleDayComparer : IEqualityComparer<ScheduleDay>
{
public bool Equals(ScheduleDay x, ScheduleDay y)
{
return x.Id == y.Id && x.DayFunctions
.SequenceEqual(y.DayFunctions);
}
public int GetHashCode(ScheduleDay x)
{
return x.Id.GetHashCode() ^ x.DayFunctions
.Aggregate(0, (a, y) => a ^ y.GetHashCode());
}
}
// MODEL FOR VIEW
public class ScheduleWeekViewModel
{
public ScheduleWeek ScheduleWeek { get; set; }
public ScheduleHelpers ScheduleHelpers { get; set; }
}
// MVC VIEW
@{
var scheduleDayComparer = new ScheduleHelpers.ScheduleDayComparer(); // <-- ADDED
var scheduledays = Model.ScheduleHelpers
.GetScheduleDaysWithDayFunctions(station.Id,
employee.Id.ToString(),
Model.ScheduleWeek.Id).Result
.GroupBy(x => x, scheduleDayComparer) // <-- ADDED
.Select(g => g.First()) // <-- ADDED
.ToList(); // <-- ADDED
//.GroupBy(sd => new
// {
// sd.Shift.Id,
// sd.DayFunctions // <-- this causes the grouping to break
// })
//.Select(g => g.First());
}
<table>
@foreach (var scheduleday in scheduledays)
{
<tr>
<td>
<text>SHIFT: @scheduleday.Shift.Name </text>
</td>
<td>
@foreach (var df in scheduleday.DayFunctions)
{
<text>DAY FUNCTIONS: @df.FunctionId </text>
}
</td>
</tr>
}
</table>
// CONTROLLER ACTION
public async Task<IActionResult> LocationScheduler()
{
var vm = new ScheduleWeekViewModel{};
var user = await _userManager.GetUserAsync(User);
vm.Employees = await _tcomsHelpers.GetEmployeesOfSupervisor(user);
vm.ScheduleDays = await _scheduleHelpers.GetScheduleWeekDaysForScheduler(vm.Employees);
vm.ScheduleWeek = await _scheduleHelpers.GetCurrentScheduleWeek();
vm.ScheduleHelpers = _scheduleHelpers;
return View(vm);
}
【问题讨论】:
-
C# 不知道,如何比较两个列表进行分组。您必须为两个列表编写自定义比较函数
-
我不是在比较两个列表。这是列表中的列表。
-
GroupBy需要一些函数来比较对象。对于默认类型(整数、字符串),它使用默认比较。但是像List<T>这样的复杂类型需要自定义。阅读有关GroupBy方法的更多信息 -
@Backs 那是票。感谢您指点我查看 IEqualityComparer!在您帮助我缩小搜索范围后,我找到了这个link。请回答,这样我就可以给你信用,谢谢!
-
@Emo333 您对
IEqualityComparer<T>和SequenceEquals调用的实现除了具有相同的内容外,还需要相同的序列。这可能有问题,具体取决于您的要求。您的哈希码方法也不是最佳的,因为^可能会导致“误报”。更好的实现使用小的素数和乘法,如下所示:Aggregate(0, (a, y) => 31*a + y.GetHashCode());最后,请注意您需要在DayFunction类中实现HashCode和Equals。
标签: c# asp.net-mvc linq .net-core