समस्या: Distinct() फ़ील्ड के अनुसार फ़िल्टर नहीं कर सकता
\n\nकल्पना करें: आपके पास ग्राहकों की एक सूची है, और उसमें ईमेल के आधार पर डुप्लिकेट घुस गए हैं। आप लिखते हैं:
\n\nvar uniqueClients = clients.Distinct().ToList();\n\nऔर आश्चर्यचकित होकर पाते हैं कि डुप्लिकेट कहीं गायब नहीं हुए। क्यों? क्योंकि मानक Distinct() पूरे ऑब्जेक्ट्स की तुलना संदर्भ (या Equals द्वारा, यदि आपने इसे ओवरराइड किया है) से करता है। यह नहीं जानता कि आपके लिए "विशिष्टता" का अर्थ एक अद्वितीय Email है, न कि क्लास का एक अद्वितीय इंस्टेंस।
यह प्रश्न LINQ पर Stack Overflow पर सबसे लोकप्रिय प्रश्नों में से एक है (500 हजार से अधिक बार देखा गया)। और आज हम C# में इस समस्या को हल करने के 3 कार्यशील तरीकों पर चर्चा करेंगे। चलिए शुरू करते हैं!
\n\nतरीका 1. GroupBy + First (क्लासिक तरीका)
\n\nसबसे सरल और समझने योग्य तरीका, जिसमें तृतीय-पक्ष लाइब्रेरी स्थापित करने की आवश्यकता नहीं है। विचार: ऑब्जेक्ट्स को वांछित प्रॉपर्टी के अनुसार समूहित करें, फिर प्रत्येक समूह से पहला तत्व लें।
\n\nvar uniqueByEmail = clients\n .GroupBy(c => c.Email)\n .Select(g => g.First())\n .ToList();\n\nयह कैसे काम करता है:
\n- \n
GroupBy(c => c.Email)— कलेक्शन को समूहों में विभाजित करता है, जहाँ कुंजी ईमेल है। \n Select(g => g.First())— प्रत्येक समूह से पहला मिलने वाला ऑब्जेक्ट लेता है। \n - शेष डुप्लिकेट हटा दिए जाते हैं। \n
लाभ:
\n- \n
- "बॉक्स से बाहर" काम करता है (केवल
using System.Linq;आवश्यक है)। \n - शुरुआती के लिए भी सहज रूप से समझ में आता है। \n
- मूल क्रम बनाए रखता है (पहला मिलने वाला ऑब्जेक्ट रहता है)। \n
नुकसान:
\n- \n
- बड़े डेटा पर थोड़ा धीमा (समूह बनाने की आवश्यकता है)। \n
- कोड अपेक्षा से थोड़ा अधिक शब्दाडंबरपूर्ण है। \n
तरीका 2. MoreLinq और DistinctBy (सुंदरता)
\n\nयदि आप तृतीय-पक्ष लाइब्रेरी से नहीं डरते हैं, तो MoreLinq एक आदर्श विधि DistinctBy प्रदान करता है। यह बिल्कुल वही करता है जो आप Distinct से उम्मीद करते हैं — प्रॉपर्टी के अनुसार फ़िल्टर करता है।
NuGet के माध्यम से स्थापना:
\nInstall-Package MoreLinq\n\nउपयोग:
\nusing MoreLinq;\n\nvar uniqueByEmail = clients.DistinctBy(c => c.Email).ToList();\n\nएक पंक्ति — और सब कुछ तैयार है। अंदर, DistinctBy HashSet का उपयोग करता है और O(n) में काम करता है।
लाभ:
\n- \n
- अत्यंत संक्षिप्त और पढ़ने योग्य कोड। \n
- उच्च प्रदर्शन। \n
- लाइब्रेरी अच्छी तरह से परीक्षण की गई है (10 मिलियन से अधिक डाउनलोड)। \n
नुकसान:
\n- \n
- प्रोजेक्ट में निर्भरता जोड़ने की आवश्यकता है। \n
- सभी टीमें तृतीय-पक्ष लाइब्रेरी की अनुमति नहीं देती हैं। \n
तरीका 3. स्वयं का IEqualityComparer (अधिकतम नियंत्रण)
\n\nयह तरीका तब उपयुक्त है जब आप लाइब्रेरी नहीं जोड़ना चाहते हैं, लेकिन तुलना तर्क को कई स्थानों पर पुन: उपयोग करना चाहते हैं। अपना स्वयं का कम्पेरेटर बनाएँ:
\n\npublic class ClientEmailComparer : IEqualityComparer<Client>\n{\n public bool Equals(Client x, Client y)\n {\n if (ReferenceEquals(x, y)) return true;\n if (x is null || y is null) return false;\n return x.Email == y.Email;\n }\n\n public int GetHashCode(Client obj)\n {\n return obj.Email?.GetHashCode() ?? 0;\n }\n}\n\nउपयोग:
\nvar comparer = new ClientEmailComparer();\nvar uniqueByEmail = clients.Distinct(comparer).ToList();\n\nलाभ:
\n- \n
- तुलना तर्क पर पूर्ण नियंत्रण। \n
- कम्पेरेटर का
Contains,Except,Unionआदि में पुन: उपयोग किया जा सकता है। \n - बाहरी लाइब्रेरी की आवश्यकता नहीं है। \n
नुकसान:
\n- \n
- बहुत सारा बॉयलरप्लेट कोड। \n