Question

J'ai eu du mal à articuler les différences entre ILookup<TKey, TVal> et IGrouping<TKey, TVal> , et je suis curieux de savoir si je comprends bien maintenant. LINQ aggravé le problème en produisant des séquences d'articles de IGrouping tout en me donnant une méthode d'extension de ToLookup. On avait l'impression qu'ils étaient les mêmes jusqu'à ce que je regardais de plus près.

var q1 = 
    from n in N
    group n by n.MyKey into g
    select g;
// q1 is IEnumerable<IGrouping<TKey, TVal>>

Ce qui est équivalent à:

var q2 = N.GroupBy(n => n.MyKey, n => n);
// q2 is IEnumerable<IGrouping<TKey, TVal>>

Ce qui ressemble beaucoup à:

var q3 = N.ToLookup(n => n.MyKey, n => n);
// q3 is ILookup<TKey, TVal>

Ai-je raison des analogies suivantes?

  1. Un IGrouping<TKey, TVal> est un groupe unique (à savoir une séquence à clé), analogue à KeyValuePair<TKey, TVal> dont la valeur est en fait une séquence d'éléments (plutôt que d'un seul élément)
  2. Un IEnumerable<IGrouping<TKey, TVal>> est une séquence de ceux (semblable à ce que vous obtenez lorsque vous parcourez un IDictionary<TKey, TVal>
  3. Un ILookup<TKey, TVal> est plus comme un IDictionary<TKey, TVal> dont la valeur est en fait une séquence d'éléments
Était-ce utile?

La solution

Oui, tous ceux qui sont corrects.

Et ILookup<TKey, TValue> étend également IEnumerable<IGrouping<TKey, TValue>> de sorte que vous pouvez parcourir toutes les clés / paires de collecte ainsi que (ou au lieu de) juste à la recherche des clés particulières.

Je pense essentiellement de ILookup<TKey,TValue> comme comme IDictionary<TKey, IEnumerable<TValue>>.

Gardez à l'esprit que ToLookup est une opération « faire maintenant » (exécution immédiate) alors qu'un GroupBy est reporté. Comme il arrive, avec la façon dont « tirer LINQ » fonctionne, quand vous commencez à tirer IGroupings du résultat d'un GroupBy, il doit lire toutes les données de toute façon (parce que vous ne pouvez pas changer le groupe à mi-chemin), alors que dans d'autres implémentations il peut être en mesure de produire un résultat de streaming. (Il ne en push LINQ,. Je pense LINQ aux événements être le même)

Autres conseils

Il y a une autre différence importante entre iLookup et IDictionary: l'ancien immuabilité impose en ce sens que ucune méthodes pour modifier les données (sauf si le consommateur effectue un casting explicite). En revanche, IDictionary a des méthodes comme « Ajouter », qui permettent de modifier les données. Ainsi, dans la perspective de programmation fonctionnelle et / ou la programmation parallèle, iLookup est plus agréable. (Je veux seulement il y avait aussi une version de iLookup qui affecte une seule valeur à une clé plutôt que d'un groupe.)

(. BTW, il semble intéressant de souligner que la relation entre IEnumerable et IList est un peu semblable à celle entre iLookup et IDictionary -. Le premier est immuable, celle-ci n'est pas)

GroupBy et ToLookUp a presque la même fonctionnalité SAUF ceci: Référence

  

GroupBy: L'opérateur retourne GroupBy groupes d'éléments basés sur certains   valeur clé. Chaque groupe est représenté par IGrouping   objet.

     

ToLookup: ToLookup est le même que GroupBy; la seule différence   est l'exécution de GroupBy est différé tandis que l'exécution est ToLookup   immédiate.

Permet d'effacer la différence en utilisant le code de l'échantillon. supposons que nous avons une classe représentant le modèle Person:

class Personnel
{
    public int Id { get; set; }
    public string FullName { get; set; }
    public int Level { get; set; }
}

après que nous définissons une liste de personnels comme suit:

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

Maintenant je dois obtenir le personnels regroupés selon leur niveau. J'ai deux approche ici. en utilisant GroupBy ou ToLookUp. Si j'utilise GroupBy, comme indiqué précédemment, il utilisera l'exécution différée, cela signifie que lorsque vous itérer la collection l'élément suivant peut ou ne peut pas être calculé jusqu'à ce qu'il soit nécessaire.

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

Dans le code ci-dessus, je tout d'abord regroupé les personnels, mais avant itérer, j'ai enlevé quelques personnels. Comme GroupBy utilise l'exécution différée, de sorte que le résultat final ne comprend pas les éléments supprimés, parce que le regroupement sera de calcul, dans le point de foreach ici.

Sortie:

2
2 >>> P2 >>> 2
5 >>> P5 >>> 2
6 >>> P6 >>> 2
7 >>> P7 >>> 2

Mais si je réécris le code ci-dessus comme ci-dessous: (notez que le code est identique au code précédent, sauf GroupBy est remplacé par 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 utilise une exécution immédiate, cela signifie que lorsque j'appelle la méthode de ToLookUp, le résultat est généré et le groupe est appliqué, de sorte que si je supprimer tout élément de personnels avant l'itération, cet effet habitude le résultat final.

Sortie:

1
1 >>> P1 >>> 1
3 >>> P3 >>> 1
4 >>> P4 >>> 1
2
2 >>> P2 >>> 2
5 >>> P5 >>> 2
6 >>> P6 >>> 2
7 >>> P7 >>> 2

Note:. GroupBy et ToLookUp retournent toutes deux différents types trop

Vous pouvez utiliser ToDictionary au lieu de ToLookup, mais vous devez faire attention à ceci: ( référence )

  

L'utilisation de ToLookup () est très similaire à celle de ToDictionary (),   à la fois vous permettent de spécifier les sélecteurs clés, sélecteurs de valeur, et   . comparateurs La principale différence est que ToLookup () permet (et   attend) les clés en double, tandis que ToDictionary () ne fonctionne pas

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top