سؤال

لقد كنت تواجه مشكلة في توضيح الاختلافات بين 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. أ IGrouping<TKey, TVal> هي مجموعة واحدة (أي تسلسل مفاعل)، مماثلة ل KeyValuePair<TKey, TVal> حيث القيمة هي في الواقع سلسلة من العناصر (بدلا من عنصر واحد)
  2. أ IEnumerable<IGrouping<TKey, TVal>> هو سلسلة من هؤلاء (مماثلة لما تحصل عليه عند التكرار IDictionary<TKey, TVal>
  3. أ ILookup<TKey, TVal> هو أشبه IDictionary<TKey, TVal> حيث القيمة هي في الواقع سلسلة من العناصر
هل كانت مفيدة؟

المحلول

نعم، كل هذه صحيحة.

و ILookup<TKey, TValue> يمتد أيضا IEnumerable<IGrouping<TKey, TValue>> حتى تتمكن من تكرار جميع أزواج المفتاح / المجموعة وكذلك (أو بدلا من) مجرد البحث عن مفاتيح معينة.

أعتقد أساسا ILookup<TKey,TValue> كما هو مثل IDictionary<TKey, IEnumerable<TValue>>.

نضع في اعتبارنا أن ToLookup هي عملية "هل الآن" (الإعدام الفوري) في حين أ GroupBy مؤجلة. كما يحدث، مع الطريقة التي "سحب LinQ" يعمل، عندما تبدأ السحب IGroupingS من نتيجة GroupBy, ، يجب أن تقرأ جميع البيانات على أي حال (نظرا لأنك لا تستطيع تبديل Group Midway)، في حين أنه في تطبيقات أخرى قد تكون قادرة على إنتاج نتيجة تدفق. (يفعل في دفع LINQ؛ أتوقع أن يكون LinQ للأحداث هو نفسه.)

نصائح أخرى

هناك فرق آخر مهم بين ILOOKUP و IDITIONARY: إن السابق يفرض الاستخدام غير المتحقاق بمعنى أن فيما يلي أي طرق لتغيير البيانات (باستثناء عندما يقوم المستهلك بإلقاء صريح). على النقيض من ذلك، فإن التصدي له أساليب مثل "إضافة" والتي تسمح بتغيير البيانات. لذلك، من وجهة نظر البرمجة الوظيفية و / أو البرمجة الموازية، ILOOKUP هو أجمل. (أتمنى فقط أن هناك أيضا إصدار من ILOOKUP يعين قيمة واحدة فقط إلى مفتاح بدلا من مجموعة.)

(راجع للشغل.، يبدو أن الأمر يستحق الإشارة إلى أن العلاقة بين iEnumerable و iilist هي مشابهة إلى حد ما بين ILOOKUP و IDECTIONARY - السابق غير قابل للتغيير، وهذا الأخير ليس كذلك.

GroupBy و ToLookUp لديه نفس الوظيفة تقريبا إلا هذه: المرجعي

GroupBy: يقوم مشغل GroupBy بإرجاع مجموعات من العناصر بناء على بعض القيمة الرئيسية. تمثل كل مجموعة بواسطة كائن Igrouping.

TOLOKUP: TOLOOKUP هو نفسه Gobby؛ الفرق الوحيد هو تنفيذ 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 كلا عودة أنواع مختلفة أيضا.

قد تستخدم التبديل بدلا من Tolookup، لكنك بحاجة إلى الانتباه إلى هذا :(المرجعي)

إن استخدام Tolookup () يشبه إلى حد كبير ما من التبديل ()، كلاهما يسمح لك بتحديد المحددات الرئيسية ومحددات القيمة والمقارنة. الفرق الرئيسي هو أن Tolookup () يسمح (ويتوقع) المفاتيح المكررة في حين أن التبديل () لا

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top