使用这样的数据(作为旁注,json文件中的这些单独组件正确地称为什么 - 记录?items?elements?objects?jsonpiecesparts?):
[
{
"WeekOfAssignment": "2016-04-04T00:00:00",
"TalkType": 1,
"StudentID_FK": 32,
"AssistantID_FK": 0,
"CounselPoint": 10,
"HasBeenEmailed": false,
"SlipHasBeenPrinted": false
},
{
"WeekOfAssignment": "2016-04-11T00:00:00",
"TalkType": 1,
"StudentID_FK": 43,
"AssistantID_FK": 0,
"CounselPoint": 39,
"HasBeenEmailed": false,
"SlipHasBeenPrinted": false
},
{
"WeekOfAssignment": "2016-04-11T00:00:00",
"TalkType": 2,
"StudentID_FK": 44,
"AssistantID_FK": 40,
"CounselPoint": 12,
"HasBeenEmailed": false,
"SlipHasBeenPrinted": false
},
{
"WeekOfAssignment": "2016-04-11T00:00:00",
"TalkType": 4,
"StudentID_FK": 4,
"AssistantID_FK": 24,
"CounselPoint": 23,
"HasBeenEmailed": false,
"SlipHasBeenPrinted": false
},
{
"WeekOfAssignment": "2016-04-11T00:00:00",
"TalkType": 6,
"StudentID_FK": 1,
"AssistantID_FK": 41,
"CounselPoint": 42,
"HasBeenEmailed": false,
"SlipHasBeenPrinted": false
},
{
"WeekOfAssignment": "2016-04-25T00:00:00",
"TalkType": 1,
"StudentID_FK": 19,
"AssistantID_FK": 0,
"CounselPoint": 2,
"HasBeenEmailed": false,
"SlipHasBeenPrinted": false
},
{
"WeekOfAssignment": "2016-04-25T00:00:00",
"TalkType": 2,
"StudentID_FK": 13,
"AssistantID_FK": 12,
"CounselPoint": 41,
"HasBeenEmailed": false,
"SlipHasBeenPrinted": false
},
{
"WeekOfAssignment": "2016-04-25T00:00:00",
"TalkType": 4,
"StudentID_FK": 20,
"AssistantID_FK": 42,
"CounselPoint": 11,
"HasBeenEmailed": false,
"SlipHasBeenPrinted": false
},
{
"WeekOfAssignment": "2016-04-25T00:00:00",
"TalkType": 6,
"StudentID_FK": 36,
"AssistantID_FK": 39,
"CounselPoint": 31,
"HasBeenEmailed": false,
"SlipHasBeenPrinted": false
}
]
...我想根据StudentID_FK与AssistantID_FK合作的次数来命令这些对象(或者他们被称为的任何对象),这两个对象在列表顶部被分配在一起的次数最少。 IOW,两个从未被分配在一起的应该是有序列表中的第一个项目,而那些已经被分配在一起最多的那些应该在底部。
注意:一次出现为“StudentID_FK”的人下次可能会被表示为“AssistantID_FK”,反之亦然。
要确定这一点,需要查询整个json文件。我相信我可以得到这样的计数(假设studentlist是学生列表,如json文件中所示):
int countOfTimesWorkedTogether = GetCountOfTimesWorkedTogether(student1, student2);
private int GetCountOfTimesWorkedTogether(int student, int assistant)
{
int StudentAndAssistant = studentlist.Where(s => s.StudentID_FK == student && a => a.AssistantID_FK == assistant).Count();
int AssistantAndStudent = studentlist.Where(s => s.StudentID_FK == assistant && a => a.AssistantID_FK == student).Count();
return StudentAndAssistant + AssistantAndStudent;
}
...但是我如何在列表的LINQ查询中使用它?伯爵不是学生班的成员,那么根据这些计数可以采用什么“技巧”来订购结果呢?
我需要的是来自同一列表的两个并排排序。第一个由WeekOfAssignment排序,另一个“旁边”包含其他人的列表,按最少的时间排序,他们与当前在第一个查询中填充的checkedlistbox中突出显示的人一起工作。
在伪代码中,我最终需要的是:
List<Student> orderedStudents = studentlist.OrderBy(WeekOfAssignment);
填充checklistboxStudents。
然后这个:
List<Student> orderedAssistants = studentlist.OrderBy(CountOfTimesWorkedWithSelectedPersonInChecklistboxStudents);
...填充checklistboxAssistants;因此,每次在checklistboxStudents中选择不同的学生时,必须重新运行第二个查询,并重新排序checklistboxAssistants。
我担心我没有清楚地解释这个问题的本质。它是:
每周都有一(3)份作业需要两名学生:“学生”和助理。
每个学生都可以扮演任何角色;他们可以给出讲话2,3,4,5,6或7.偶数是学生作业,奇数是辅助作业。每个列表都是唯一的 - 那些预定将被分配为#2的列表,那些将被分配为#3的列表,等等。
因此,六个列表中的每一个都是学生超集列表的唯一子集,在任何给定的一周中,每个列表的总数约为1/6(它们将在下一周移动到下一个列表)。
所以我需要将列表3中的列表与列表2中的列表进行比较,将列表5中的列表与列表4中的列表进行比较,将列表7中的列表与列表6中的列表进行比较。
有一个学生列表可以跟踪学生的数据,例如给出的最后一个作业(#/谈话类型和日期)等。作业清单(摘录如上所示)包含作业/周,作为“学生”(StudentID_FK)的学生,以及作为该学生助理的学生(AssistantID_FK)。
所以,重新思考它,我或许可以订购这样的助手(伪代码):
0)将“OptionalOrderingVal”成员添加到Students类:
public int OptionalOrderingVal { get; set; }
首先,根据下一个分配类型获取初始助手列表,按上次分配日期排序;例如,对于分配#3,它支持#2:
var RVAssistantsList = studentlist.Where(t => t.talkType == 3).OrderBy(w => weekOfLastAssignment);
接下来,创建该子列表的新版本,填充OptionalOrderingVal成员:
int countOfAssignmentsWithStudent = 0;
int StudentId = comboboxRVStudent.SelectedValue;
foreach (Student assistant in RVAssistantsList)
{
countOfAssignmentsWithStudent = assignmentsList.Where(StudentID_FK == StudentId && AssistantID_FK == AssistantId || StudentID_FK == AssistantId && AssistantID_FK == StudentId);
assistant.OptionalOrderingVal = countOfAssignmentsWithStudent;
}
然后,按新值排序助理列表:
RVAssistantsList = RVAssistantsList
.OrderBy(o => o.OptionalOrderingVal)
.ThenBy(w => w.WeekOfLastAssignment)
.ToList();
最后,将该列表分配给相应的检查表:
checklistboxRVAssistants.Items = RVAssistantsList;
我可以称之为kludgelent或eligy; YMMV。
答案 0 :(得分:1)
如果您有这样的模型:
public class Student
{
public DateTime WeekOfAssignment { get; set; }
public int TalkType { get; set; }
public int StudentID_FK { get; set; }
public int AssistantID_FK { get; set; }
public int CounselPoint { get; set; }
public bool HasBeenEmailed { get; set; }
public bool SlipHasBeenPrinted { get; set; }
}
您可以使用匿名类型按属性StudentID_FK
和AssistantID_FK
进行linq查询分组,并根据其大小对此组进行排序,然后再次加入元素。
根据StudentID_FK
和AssistantID_FK
对出现在列表中的次数,排序的元素排序,首先是最低的次数:
var result = studentlist.GroupBy(m => new
{
A = Math.Min(m.StudentID_FK, m.AssistantID_FK), // This gets pairs like (1, 2) and (2, 1)
B = Math.Max(m.StudentID_FK, m.AssistantID_FK) // as the same (1, 2)
})
.OrderBy(g => g.Count())
.SelectMany(g => g)
.ToList();
答案 1 :(得分:1)
您想要的是按一对学生ID作为学生或助理出现的次数进行排序,反之亦然。因此:
var orderedAssistants = studentlist
.OrderBy(a => GetCountOfTimesWorkedTogether(studentlist, a.StudentID_FK, a.AssistantID_FK))
.ToList();
使用
private static int GetCountOfTimesWorkedTogether(IEnumerable<Student> studentList, int id1, int id2)
{
var count = studentList.Where(s => s.StudentID_FK == id1 && s.AssistantID_FK == id2 || s.StudentID_FK == id2 && s.AssistantID_FK == id1).Count();
return count;
}
但请注意,这可以是学生人数的二次方。你要找的是两个学生一起工作的时间 - 学生+助理,反之亦然。表示与订单无关的组合的标准方法是HashSet<T>
,其中T
将是用于表示学生ID的类型。然后,您可以使用HashSet<T>.CreateSetComparer()
按内容相等性对集合进行分组:
因此,以下不应该是二次的:
var orderedAssistants = studentlist
.GroupBy(s => (new[] { s.AssistantID_FK, s.StudentID_FK }).ToSet(), HashSet<int>.CreateSetComparer())
.OrderBy(g => g.Count())
.SelectMany(g => g)
.ToList();
使用
public static class EnumerableExtensions
{
public static HashSet<T> ToSet<T>(this IEnumerable<T> source)
{
return new HashSet<T>(source);
}
}