Go में Set नहीं है: क्यों और बिना अंतर्निहित सेट के कैसे काम करें

शुरुआती लोगों के लिए ऑनलाइन Python प्रशिक्षक

Python आसानी से सीखें बिना सिद्धांत के बोझ के। स्वचालित जांच के साथ व्यावहारिक कार्य हल करें और ब्राउज़र में सीधे कोड लिखें।

पाठ्यक्रम शुरू करें

"मेरा Set कहाँ है?" — Go डेवलपर की आत्मा की पुकार

\n\n

यदि आप Python, JavaScript या Java से Go में आए हैं, तो देर-सबेर आप यह प्रश्न पूछेंगे: "आखिर मेरा प्रिय Set कहाँ है?" — और यह सामान्य है। Stack Overflow पर विषय "Golang why don't we have a set datastructure" ने हजारों व्यूज़ और दर्जनों गर्म चर्चाएँ एकत्र की हैं। डेवलपर्स अद्वितीय तत्वों वाले सुविधाजनक सेट के आदी हैं, जबकि Go केवल arrays, slices और maps प्रदान करता है। इस लेख में हम Go के निर्माताओं के दर्शन को समझेंगे, Set का अनुकरण करना सीखेंगे और अपना स्वयं का न्यूनतम कार्यान्वयन भी लिखेंगे।

\n\n

Go के निर्माताओं ने मानक लाइब्रेरी में Set क्यों नहीं जोड़ा?

\n\n

इसका उत्तर भाषा के न्यूनतमवाद और व्यावहारिकता में छिपा है। Go टीम (रॉब पाइक, केन थॉम्पसन, रॉबर्ट ग्रिसेमर) ने सिद्धांत का पालन किया: "यदि कुछ एक भाषा निर्माण से किया जा सकता है, तो संस्थाओं का प्रसार न करें।" Go में map केवल एक शब्दकोश नहीं है, बल्कि एक सार्वभौमिक कंटेनर है। यह पहले से ही कुंजियों की विशिष्टता का समर्थन करता है, जो सेट का मुख्य गुण है।

\n\n

दर्शन: "कम जादू - अधिक स्पष्टता"

\n\n

Python के विपरीत, जहाँ set अपने स्वयं के तरीकों (.add(), .union()) के साथ एक अलग प्रकार है, Go में भाषा को जटिल न करने का निर्णय लिया गया। एक अलग संरचना क्यों लिखें जब map[T]struct{} वही काम करता है? यह मानक लाइब्रेरी में जगह बचाता है और शुरुआती लोगों के लिए प्रवेश की बाधा को कम करता है। मुख्य बात है map को set के रूप में सही ढंग से उपयोग करना सीखना।

\n\n

Go में Set का अनुकरण कैसे करें: तीन कार्यशील दृष्टिकोण

\n\n

आइए अभ्यास की ओर बढ़ते हैं। यहाँ बताया गया है कि केवल Go के मानक साधनों का उपयोग करके सेट को कैसे कार्यान्वित किया जा सकता है।

\n\n

1. सबसे लोकप्रिय: map[type]struct{}

\n\n

यह Go समुदाय में मानक दृष्टिकोण है। struct{} क्यों? क्योंकि खाली संरचना मेमोरी (0 बाइट) नहीं लेती है — तत्व के "अस्तित्व" के चिह्न के लिए आदर्श।

\n\n
package main\n\nimport "fmt"\n\nfunc main() {\n    // पूर्णांकों का एक सेट बनाएँ\n    set := make(map[int]struct{})\n\n    // तत्व जोड़ें\n    set[1] = struct{}{}\n    set[2] = struct{}{}\n    set[3] = struct{}{}\n    set[1] = struct{}{} // डुप्लिकेट को अनदेखा किया जाता है\n\n    // अस्तित्व की जाँच\n    if _, exists := set[2]; exists {\n        fmt.Println("2 सेट में है")\n    }\n\n    // हटाना\n    delete(set, 3)\n\n    // पुनरावृत्ति\n    for key := range set {\n        fmt.Println(key)\n    }\n}
\n\n

लाभ: मानों के लिए शून्य मेमोरी आवंटन, सरलता। नुकसान: कोई .Add() या .Contains() विधियाँ नहीं हैं — सब कुछ map सिंटैक्स के माध्यम से किया जाता है।

\n\n

2. विधियों के साथ स्वयं का प्रकार

\n\n

यदि आपको एक स्वच्छ API चाहिए, तो map को एक संरचना में लपेटें:

\n\n
package main\n\nimport "fmt"\n\n// Set — generic सेट (Go 1.18+)\ntype Set[T comparable] struct {\n    items map[T]struct{}\n}\n\n// NewSet एक नया Set बनाता है\nfunc NewSet[T comparable]() *Set[T] {\n    return &Set[T]{items: make(map[T]struct{})}\n}\n\n// Add एक तत्व जोड़ता है\nfunc (s *Set[T]) Add(item T) {\n    s.items[item] = struct{}{}\n}\n\n// Contains उपस्थिति की जाँच करता है\nfunc (s *Set[T]) Contains(item T) bool {\n    _, ok := s.items[item]\n    return ok\n}\n\n// Size आकार लौटाता है\nfunc (s *Set[T]) Size() int {\n    return len(s.items)\n}\n\nfunc main() {\n    intSet := NewSet[int]()\n    intSet.Add(10)\n    intSet.Add(20)\n    fmt.Println(intSet.Contains(10)) // true\n    fmt.Println(intSet.Size())       // 2\n}
\n\n

यह पहले से ही Go में एक पूर्ण set datastructure जैसा दिखता है। जेनेरिक (generics) संस्करण 1.18 में दिखाई दिए, इसलिए कोड आधुनिक परियोजनाओं पर काम करता है।

\n\n

3. struct{} के बजाय bool का उपयोग

\n\n

कुछ लोग map[T]bool का उपयोग करते हैं, लेकिन यह मान पर 1 बाइट खर्च करता है। अधिकांश मामलों में अंतर नगण्य है, लेकिन यदि आप उच्च-लोड सेवा लिख रहे हैं — तो struct{} पर टिके रहना बेहतर है।

\n\

ब्लॉग

पुस्तक अनुशंसाएँ