Как упорядочить и сгруппировать в запросе Linq к объектам? - PullRequest
1 голос
/ 28 сентября 2010

Как заказать и сгруппировать в запросе Linq?

Я пытался ..

Dim iPerson = From lqPersons In objPersons Where Len(lqPersons.Person) > 0 Group lqPersons By key = lqPersons.Name Into Group Order By Group descending Select Group, key

    For Each i In iPerson
        tmp = tmp & vbNewLine & i.key & ", " & i.Group.Count
    Next

Вышеприведенное работает, если я удаляю предложение Order By Group Descending, но при этом я получаю сообщение об ошибке в выражении Next

Как минимум один объект должен реализовывать IComparable.

Мой запрос - получить список людей в моем классе / объекте с указанием того, сколько раз их имя используется в качестве элемента класса / объекта.

* 1016 Т.е. *

Джо, 4 | Джеймс, 5 | Майк, 4

У кого-нибудь есть идеи, что я делаю не так?

Ответы [ 5 ]

3 голосов
/ 28 сентября 2010

Ваш запрос в порядке (нет проблем с использованием Group в VB.NET в качестве имени, кстати ... на самом деле вы ДОЛЖНЫ использовать Group, так что не беспокойтесь об этом), за исключением того, что у вас должен быть ключ Order By.

ps Протестировано.

РЕДАКТИРОВАТЬ: Для полноты вы можете переименовать вашу группу следующим образом:

Dim iPerson = From lqPersons In objPersons
              Where Len(lqPersons.Person) > 0
              Group lqPersons By key = lqPersons.Name Into g = Group
              Order By key Descending
              Select g, key

Однако это не имеет ничего общего с вашей проблемой ... простопрояснение этого вопроса.

2 голосов
/ 29 сентября 2010

Вы получаете ошибку в следующем операторе, потому что запрос выполняется, когда выполняется цикл For Each (он называется выполнение defferd ).

Ошибка фактически говорит о том, что вы не можете выполнить Ordey By Group, потому что IGrouping не реализует IComparable, поэтому результат вашего Group By заявления не может быть упорядочен Сам IGrouping.

Заказывать нужно по количеству элементов IGrouping объектов.


Попробуйте это (заметьте, что я не знаю, как выглядят ваши занятия ...):

Dim objPersons = New YourClass() {New YourClass("Joe"), _
                                  New YourClass("Joe"), _
                                  New YourClass("Joe"), _
                                  New YourClass("James"), _
                                  New YourClass("James"), _
                                  New YourClass("James"), _
                                  New YourClass("James"), _
                                  New YourClass("Mike"), _
                                  New YourClass("Mike")}

Dim query = objPersons.Where(function(p) p.Person > 0) _
                      .GroupBy(Function(p) p.Name) _
                      .OrderByDescending(Function(g) g.Count) _
                      .Select(function(g) g.Key & ", " & g.Count())


For Each s In query
    Console.WriteLine(s)
Next

Вывод:

James, 4
Joe, 3
Mike, 2
2 голосов
/ 28 сентября 2010

Извините мой C #, но вы не могли бы сделать что-то вроде ...

objPersons.Where(p=> p.Person > 0).GroupBy(p => p.Name).Select(p => new { Name= p.Key, Number = p.Count()}).OrderByDescending(p=> p.Number);

Основная идея:

  1. GroupBy, как вы сделали
  2. Выберите новый объект, используя свой Ключ (Имя) и посчитав, сколько в этой группе
  3. Порядок по убыванию
0 голосов
/ 28 сентября 2010

Я сделал нечто подобное в VB. У меня это тоже есть в моем блоге. Но в основном это SQL, с которого я начал.

SELECT orgno, psno, sche, projid, RecType, 
SUM(OBBudExpAmt) AS OBBudExpAmt, 
SUM(ABBudEncAmt) AS ABBudEncAmt
FROM tbl908_BudSPDGrps 
WHERE orgno = '210'
GROUP BY orgno, psno,  sche, projid, RecType

А вот соответствующий LINQ.Довольно понятно.Надеюсь, это поможет вам.

0 голосов
/ 28 сентября 2010

является ли lqPersons.Name строкой или структурой или классом, содержащим имена, имена, отчества и т. Д.?Если это первое, вам должно быть хорошо с этим, так как строки IComparable.Если Name является объектом некоторого пользовательского класса, вам необходимо либо реализовать IComparable для этого класса (предоставляя метод CompareTo (), используемый для алгоритмов сортировки), либо упорядочить по «примитивному» под-свойству Name, например LastName.

РЕДАКТИРОВАТЬ: Просто видел что-то еще.Когда вы используете Group By, получаемый объект - это Lookup;в основном это KeyValuePair с коллекцией значений вместо одного.Поиски не сопоставимы.Поэтому вместо упорядочения по группе попробуйте упорядочить по ключевому идентификатору для этой группы (lqPersons.Name).

...