Лямбда наименее встречающийся элемент - PullRequest
1 голос
/ 02 декабря 2011

У меня есть класс, который выглядит следующим образом:

public class TaughtSubject
{
    public int TaughtSubjectId { get; set; }

    public int TeacherId { get; set; }
    public Teacher Teacher { get; set; }

    public int FormId { get; set; }
    public Form FormId { get; set; }

    public int SubjectId { get; set; }
    public Subject Subject { get; set; }
}

Я получил список этих объектов и хочу получить наименее встречающийся объект по SubjectId, а затем по FormId.Я также хочу вернуть первый целый элемент.Не только свойство.

Вот моя попытка:

var teacher = taughtSubjects.GroupBy(t => t.SubjectId).OrderBy(g => g.Count()).Select(g => g.Key).First();

Но это только возвращает SubjectId.Я хочу, чтобы весь объект учителя, а также добавить второе условие сортировки FormId.

Ответы [ 5 ]

2 голосов
/ 02 декабря 2011

Ты рядом.Вам нужен первый элемент Lookup (результат имеющегося у вас GroupBy), а затем значения в этом элементе поиска, который вы хотите сгруппировать по FormId и вернуть учителей с наименее встречающимся из них..

var teachers = taughtSubjects
   .GroupBy(ts => ts.SubjectId)
   .OrderBy(g => g.Count())
   .ThenBy(g=>g.Key) //tiebreaker
   .First() //gets the IEnumerable of Teachers that teach this least-taught subject
   .GroupBy(t=>t.FormId)
   .OrderBy(g=>g.Count())
   .ThenBy(g=>g.Key) //as a tiebreaker
   .First() //gets the teacher(s) with the lowest specified FormId.

Это вернет IEnumerable of Teachers хотя бы с одним элементом, представляющим учителя, которые преподают наименее изученный предмет с наименее используемой формой.

Understandчто в вашей системе могут быть предметы, которые вообще не преподаются.Они не будут представлены здесь, потому что не существует учителя, который учит классу.В запросе будут учитываться предметы, по крайней мере, с одним учителем.

РЕДАКТИРОВАТЬ: После перечитывания вашего вопроса, я думаю, я понимаю, что происходит.Эти «преподаваемые предметы» относятся к определенному предмету (математике, чтению, естествознанию, искусству, музыке), который преподается к определенной «форме» или «уровню обучения» (1-12 класс в системе США).

Поскольку у вас в данный момент настроен объект, возможны повторяющиеся записи для того же предмета и оценки, но они будут неразличимы, кроме поля TaughtSubjectID (которое может быть просто назначено счетчиком или идентификатором).

Было бы более разумно, независимо от того, как вы хотите, чтобы это было сделано, также включить Учителя в Предмет Обучения.Это, например, позволит вам перечислить учителей, которые преподают предмет с наименьшим количеством предметов в классе с наименьшим количеством предметов по этому предмету, или, альтернативно, как предлагает Дэвид Б., наименее обучаемое общее сочетание предмета и класса.

Какой из них вы хотите, субъективен, и есть семантическая разница.Музыка может быть наименее изучаемым предметом (предлагается только 9-12 классам), но на каждом уровне обучения ее преподают два или три учителя.Математика, с другой стороны, может преподаваться на каждом уровне обучения с большим количеством учителей в целом и, таким образом, иметь большее количество записей TaughtSubject, чем Music, но из всей группы может быть только один учитель математики 6-го класса.Нахождение наименее обученного класса наименее изученного предмета даст вам музыку 9-го класса.Нахождение наименее изученной общей комбинации предметных оценок даст вам математику 6-го класса.

1 голос
/ 02 декабря 2011

Это вторая группа, а не условие второй сортировки:

IEnumerable<TaughtSubject> firstGroup = taughtSubjects
  .GroupBy(t => t.SubjectId)
  .OrderBy(g => g.Count())
  .First()  //the taughtsubjects that are members of the smallest subject group.
  .GroupBy(t => t.FormId)
  .OrderBy(g => g.Count())
  .First(); // and of these taughtsubjects, the members of the smallest form group.

  // and the first member of those.
TaughtSubject firstElement = firstGroup.First();

Выше было указано то, что вы просили, но большинство людей хотели бы иметь наименьшую группу для данной формы и предметного спаривания. Это сделано так.

IEnumerable<TaughtSubject> firstGroup = taughtSubjects
  .GroupBy(t => new {t.FormId, t.SubjectId})
  .OrderBy(g => g.Count())
  .First();

  // and the first member of those.
TaughtSubject firstElement = firstGroup.First();
0 голосов
/ 02 декабря 2011

Вы можете просто использовать OrderBy и ThenBy:

public class foo
{
    public int e1 { get; set; }
    public int e2 { get; set; }
    public int e3 { get; set; }
    public int e4 { get; set; }

    public foo(int e1, int e2, int e3, int e4)
    {
        this.e1 = e1;
        this.e2 = e2;
        this.e3 = e3;
        this.e4 = e4;
    }

    public override string ToString()
    {
        return string.Format("e1 = {0}\te2 = {1}\te3 = {2}\te4 = {3}",
            e1, e2, e3, e4);
    }
}

public static void Main(string[] args)
{
    List<foo> foosList = new List<foo>();
    Random r = new Random((int)DateTime.Now.Ticks);

    for (int i = 0; i < 15; i++)
        foosList.Add(new foo(r.Next(20), r.Next(20), r.Next(10), r.Next(5)));

    List<foo> result = foosList.OrderBy(e => e.e4).ThenBy(e => e.e3).ToList();
    result.ForEach(e => Console.WriteLine(e));

    Console.ReadKey();
}

Выход:

e1 = 7  e2 = 4  e3 = 2  e4 = 0
e1 = 18 e2 = 12 e3 = 4  e4 = 0
e1 = 9  e2 = 8  e3 = 6  e4 = 0
e1 = 6  e2 = 8  e3 = 6  e4 = 0
e1 = 13 e2 = 14 e3 = 8  e4 = 0
e1 = 6  e2 = 15 e3 = 1  e4 = 2
e1 = 18 e2 = 10 e3 = 1  e4 = 2
e1 = 14 e2 = 3  e3 = 8  e4 = 2
e1 = 7  e2 = 3  e3 = 3  e4 = 3
e1 = 11 e2 = 6  e3 = 4  e4 = 3
e1 = 11 e2 = 17 e3 = 1  e4 = 4
e1 = 16 e2 = 1  e3 = 2  e4 = 4
e1 = 16 e2 = 11 e3 = 7  e4 = 4
e1 = 12 e2 = 5  e3 = 8  e4 = 4
e1 = 7  e2 = 7  e3 = 9  e4 = 4
0 голосов
/ 02 декабря 2011
var result = from ts in TaughtSubjects
let leastSubjId = taughtSubjects.GroupBy(t => t.SubjectId).OrderBy(g => g.Count()).Select(g => g.Key).First()
where ts.SubjectId == leastSubjId
select ts

Вы можете добавить еще одно условие, если хотите.

0 голосов
/ 02 декабря 2011

Я рекомендую вам не пытаться делать это в одном выражении. Читателю будет очень трудно понять, что происходит. Разбейте его на два выражения: одно для субъективного, другое для formid.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...