Угрозу безопасность компьютера и 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>


Я прав в следующих аналогиях?




  1. An IGrouping<TKey, TVal> - это одна группа (т. е. ключевая последовательность), аналогичная KeyValuePair<TKey, TVal> где значение фактически представляет собой последовательность элементов (а не один элемент)

  2. An IEnumerable<IGrouping<TKey, TVal>> - это последовательность тех (аналогично тому, что вы получаете при итерации над IDictionary<TKey, TVal>

  3. An ILookup<TKey, TVal> - это больше похоже на IDictionary<TKey, TVal> где значение на самом деле является последовательностью элементы

642   3  

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

    Ничего не найдено.