Угрозу безопасность компьютера и IGrouping
у меня были проблемы с артикуляцией, различия между ILookup<TKey, TVal> и IGrouping<TKey, TVal>, и мне любопытно, правильно ли я понимаю это сейчас. LINQ, которая усугубляет эту проблему путем создания последовательности IGrouping элементы, а также давая мне ToLookup метод расширения. Поэтому мне казалось, что они были одинаковыми, пока я не присмотрелся повнимательнее.
var q1 =
from n in N
group n by n.MyKey into g
select g;
// q1 is IEnumerable<IGrouping<TKey, TVal>>
что эквивалентно:
var q2 = N.GroupBy(n => n.MyKey, n => n);
// q2 is IEnumerable<IGrouping<TKey, TVal>>
, который выглядит намного например:
var q3 = N.ToLookup(n => n.MyKey, n => n);
// q3 is ILookup<TKey, TVal>
Я прав в следующих аналогиях?
- An
IGrouping<TKey, TVal>- это одна группа (т. е. ключевая последовательность), аналогичнаяKeyValuePair<TKey, TVal>где значение фактически представляет собой последовательность элементов (а не один элемент) - An
IEnumerable<IGrouping<TKey, TVal>>- это последовательность тех (аналогично тому, что вы получаете при итерации надIDictionary<TKey, TVal>
- An
ILookup<TKey, TVal>- это больше похоже наIDictionary<TKey, TVal>где значение на самом деле является последовательностью элементы
3 ответов:
Да, все это правильно.
и
ILookup<TKey, TValue>распространяется такжеIEnumerable<IGrouping<TKey, TValue>>таким образом, вы можете перебирать все пары ключ/коллекция, а также (или вместо) просто искать определенные ключи.Я в основном думаю о
ILookup<TKey,TValue>как бы то ни былоIDictionary<TKey, IEnumerable<TValue>>.имейте в виду, что
ToLookupэто операция " сделай это сейчас "(немедленное выполнение), тогда какGroupByоткладывается. Как это бывает, с тем, как работает "pull LINQ", когда вы начинаете тянутьIGroupingС результатGroupBy, он должен прочитать все данные в любом случае (потому что вы не можете переключить группу на полпути), тогда как в других реализациях он может быть в состоянии произвести потоковый результат. (Это происходит в Push LINQ; я ожидал бы, что события LINQ будут одинаковыми.)
есть еще одно важное различие между ILookup и IDictionary: первый обеспечивает неизменность в том смысле, что здесь нет методов для изменения данных (за исключением случаев, когда потребитель выполняет явное приведение). Напротив, IDictionary имеет такие методы, как" добавить", которые позволяют изменять данные. Таким образом, с точки зрения функционального программирования и/или параллельного программирования, ILookup лучше. (Я только хотел бы, чтобы была также версия ILookup, которая присваивает ключу только одно значение чем группа.)
(кстати. кажется, стоит отметить, что отношение между IEnumerable и IList несколько похоже на отношение между ILookup и IDictionary - первое является неизменным, второе-нет.)
GroupByиToLookUpимеет почти такую же функциональность за исключением это: ссылкаGroupBy: оператор GroupBy возвращает группы элементов на основе некоторых ключевая ценность. Каждая группа представлена IGrouping объект.
ToLookup: ToLookup-это то же самое, что GroupBy; единственная разница это выполнение метода groupBy откладывается, в то время как выполнение метода tolookup является немедленный.
позволяет очистить разница в использовании примера кода. предположим, что у нас есть класс, представляющий
Personмодель:class Personnel { public int Id { get; set; } public string FullName { get; set; } public int Level { get; set; } }после этого мы определяем список
personnelsкак показано ниже:var personnels = new List<Personnel> { new Personnel { Id = 1, FullName = "P1", Level = 1 }, new Personnel { Id = 2, FullName = "P2", Level = 2 }, new Personnel { Id = 3, FullName = "P3", Level = 1 }, new Personnel { Id = 4, FullName = "P4", Level = 1 }, new Personnel { Id = 5, FullName = "P5", Level =2 }, new Personnel { Id = 6, FullName = "P6", Level = 2 }, new Personnel { Id = 7, FullName = "P7", Level = 2 } };теперь мне нужно получить
personnelsсгруппировать по их уровню. У меня есть два подхода здесь. используяGroupByилиToLookUp. Если я используюGroupBy, как было указано ранее, он будет использовать отложенное выполнение, это означает, что при итерации по коллекции следующий элемент может быть вычислен или не вычислен до тех пор, пока он не будет вызван для.var groups = personnels.GroupBy(p => p.Level); personnels.RemoveAll(p => p.Level == 1); foreach (var product in groups) { Console.WriteLine(product.Key); foreach (var item in product) Console.WriteLine(item.Id + " >>> " + item.FullName + " >>> " + item.Level); }в приведенном выше коде я сначала сгруппировал
personnels, но перед итерацией я удалил некоторыеpersonnels. КакGroupByиспользует отложенное выполнение, поэтому конечный результат не будет включать удаленные элементы, потому что группировка будет вычисляться вforeachздесь.выход:
2 2 >>> P2 >>> 2 5 >>> P5 >>> 2 6 >>> P6 >>> 2 7 >>> P7 >>> 2но если я переписать приведенный выше код, как показано ниже:(обратите внимание, что код такой же, как и предыдущий код, за исключением
GroupByзаменяетсяToLookUp)var groups = personnels.ToLookup(p => p.Level); personnels.RemoveAll(p => p.Level == 1); foreach (var product in groups) { Console.WriteLine(product.Key); foreach (var item in product) Console.WriteLine(item.Id + " >>> " + item.FullName + " >>> " + item.Level); }как
ToLookUpиспользует немедленное выполнение, это означает, что когда я вызываюToLookUpметод, результат генерируется и применяется группа, так что если я удалить любой элемент изpersonnelsдо итерации это не повлияет на конечный результат.выход:
1 1 >>> P1 >>> 1 3 >>> P3 >>> 1 4 >>> P4 >>> 1 2 2 >>> P2 >>> 2 5 >>> P5 >>> 2 6 >>> P6 >>> 2 7 >>> P7 >>> 2Примечание:
GroupByиToLookUpоба возвращают разные типы тоже.вы можете использовать ToDictionary вместо ToLookUp, но вам нужно обратить внимание это:(ссылка)
использование ToLookup () очень похоже на использование ToDictionary(), оба позволяют указать ключевые селекторы, селекторы значений и компараторы. Главное отличие заключается в том, что ToLookup() позволяет (а ожидает) повторяющиеся ключи, тогда как ToDictionary () не
Comments