Как я могу заказать эти объекты json с помощью LINQ?

С такими данными (в качестве примечания, эти отдельные компоненты в файле json правильно называются что - записи? элементы? элементы? объекты? 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. Я полагаю, что мог бы получить что-то вроде этого (при условии, что список студентов - это список студентов, представленный в файле 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, а тот, что «рядом с ним», содержит список других людей, упорядоченный по наименьшему количеству раз, когда они работали с человеком, который в данный момент выделен в списке проверенных, который заполняется из этого первого запроса.

В псевдокоде мне нужно получить следующее:

List<Student> orderedStudents = studentlist.OrderBy(WeekOfAssignment);

Это заполняет checklistboxStudents.

Тогда это:

List<Student> orderedAssistants = studentlist.OrderBy(CountOfTimesWorkedWithSelectedPersonInChecklistboxStudents);

...заполняет контрольный списокПомощники; таким образом, этот второй запрос нужно будет запускать повторно, а контрольный список помощников переупорядочивать каждый раз, когда в контрольном списке студентов выбирается другой студент.

ОБНОВИТЬ

Боюсь, я не совсем ясно объяснил истинную природу этой проблемы. Это:

Каждую неделю есть несколько (3) заданий, для каждого из которых требуется два ученика: «ученик» и помощник.

Каждый ученик может играть любую роль; они могут говорить 2, 3, 4, 5, 6 или 7. Четные номера - это задания для учеников, а нечетные - задания для помощников. Каждый список уникален — те, которые должны быть назначены на 2-е место, те, которые должны быть назначены на 3-е место и т. д.

Таким образом, каждый из шести списков представляет собой уникальное подмножество списка надмножества студентов, примерно 1/6 от общего числа в каждом списке на любой данной неделе (они переходят к следующему списку на следующей неделе).

И поэтому мне нужно сравнить те, что в списке 3, с теми, что в списке 2, те, что в списке 5, с теми, что в списке 4, и те, что в списке 7, с теми, что в списке 6.

Существует список «Студенты», в котором отслеживаются данные о студентах, такие как последнее заданное задание (как #/тип выступления, так и дата) и т. д. Список «Задания» (отрывок из которого показан выше) содержит для каждого задания/недели , студент, который был "тем" студентом (StudentID_FK), и студент, который был помощником в этом случае (AssistantID_FK).

Итак, переосмыслив это, я мог бы заказать помощников примерно так (псевдокод):

0) Добавьте элемент «OptionalOrderingVal» в класс «Студенты»:

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;

Я мог бы назвать это либо глупостью, либо элигией; YMMV.


person B. Clay Shannon    schedule 04.03.2016    source источник
comment
Я думаю, что ваш счет должен обрабатывать случай, когда student == assistant предполагается, что это вообще возможно.   -  person juharr    schedule 04.03.2016
comment
Нет, ученик и помощник никогда не будут одинаковыми в одном предмете.   -  person B. Clay Shannon    schedule 04.03.2016
comment
Как вы хотите найти, если два не назначены вместе? Я имею в виду, что список составлен из тех, кто уже назначен вместе, и, возможно, есть некоторые другие студенты, которые не назначены, поэтому их имена не указаны в списке.   -  person user3473830    schedule 04.03.2016
comment
@ user3473830: Все учащиеся, чье следующее задание — помощник для рассматриваемого типа выступления, находятся во втором контрольном списке, упорядоченном по тому, как давно было выполнено их последнее задание; если у них его еще не было, они будут в верхней части списка. Затем, когда учащийся выбран в первом контрольном списке (ученик), я хочу изменить порядок содержимого контрольного списка помощника в зависимости от того, сколько времени прошло с тех пор, как они были назначены для работы со учащимся.   -  person B. Clay Shannon    schedule 05.03.2016


Ответы (2)


Если у вас есть такая модель:

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; }
}

Вы можете группировать запросы linq по свойствам StudentID_FK и AssistantID_FK, используя анонимный тип, и упорядочивать эти группы в соответствии с их размером, а затем снова объединять элементы.

Это сортирует элементы в зависимости от того, сколько раз пара 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();
person Arturo Menchaca    schedule 04.03.2016
comment
Спасибо! и, пожалуйста, смотрите мое примечание к базе данных кота выше. - person B. Clay Shannon; 05.03.2016

Что вам нужно, так это упорядочить по количеству раз, когда пара идентификаторов студента появляется как студент или помощник, или наоборот. Таким образом:

        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 — это тип, используемый для представления идентификаторов учащихся. Затем вы можете использовать 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);
    }
}
person dbc    schedule 04.03.2016
comment
Очень впечатляюще; Я, вероятно, не смогу проверить это в течение дня или двух, хотя. Я предполагаю, что оба ответа будут правильными, поэтому я вхожу в свой режим Робин Гуда и даю очки кошке с наименьшим количеством. Если выяснится, что его способ не работает (и ваш работает), я отменю голосование. Спасибо! - person B. Clay Shannon; 05.03.2016
comment
@B.ClayShannon - оба ответа должны работать. Мой более общий, другой работает специально для пар ключей, которые можно заказать. - person dbc; 05.03.2016