Swift में स्ट्रिंग्स का जादू: "बस एक कैरेक्टर लेना" क्यों एक चुनौती है
\n\nPython, JavaScript या C++ से Swift में आने वाला कोई भी डेवलपर देर-सबेर एक दीवार से टकराता है। एक साधारण सा काम: "मुझे स्ट्रिंग का तीसरा कैरेक्टर दो।" Python में यह str[2] है। JavaScript में str[2] है। Swift में... यह अधिक जटिल है। और यदि आपने कभी "Swift में स्ट्रिंग का nth कैरेक्टर प्राप्त करें" प्रश्न का उत्तर खोजा है, तो आप जानते हैं कि Stack Overflow सचमुच इस प्रश्न से भरा पड़ा है (हज़ारों व्यू, सैकड़ों वोट)।
क्यों? क्योंकि Swift स्ट्रिंग्स को बाइट्स की एक सरणी के रूप में नहीं, बल्कि एक जटिल, Unicode-संगत ग्रैफेम अनुक्रम के रूप में मानता है। और यदि आप सीधे तरीके से काम करते हैं — तो प्रदर्शन गिर सकता है, और कोड अपठनीय हो सकता है।
\n\nइस लेख में हम केवल उत्तर नहीं देंगे। हम Swift में n-वाँ कैरेक्टर प्राप्त करने के अनुकूलन का विश्लेषण करेंगे, विभिन्न दृष्टिकोणों के प्रदर्शन को देखेंगे और सर्वश्रेष्ठ का चयन करेंगे। चलिए शुरू करते हैं!
\n\nstring[2] काम क्यों नहीं करता? String.Index पर एक संक्षिप्त जानकारी
\n\nSwift में String, मनमानी पहुँच वाला Character का संग्रह नहीं है। यह इंडेक्स द्वारा पहुँच वाला संग्रह है, जो पूर्णांक नहीं हैं। ऐसा क्यों?
- \n
- Unicode और ग्रैफेम्स। एक "कैरेक्टर" में कई Unicode स्केलर हो सकते हैं (उदाहरण के लिए, इमोजी "🇷🇺" या उच्चारण वाला "é")। यदि इंडेक्स केवल Int होता, तो
str[1]आधा इमोजी लौटा सकता था। \n - प्रदर्शन। Unicode स्ट्रिंग के लिए इंडेक्स को Int के रूप में संग्रहीत करना एक समझौता है। Swift शुरुआत और अंत तक O(1) पहुँच का उपयोग करता है, लेकिन मनमाने इंडेक्स के लिए स्ट्रिंग को पार करना पड़ता है। \n
इसलिए Swift में nth कैरेक्टर प्राप्त करने का मानक तरीका इस प्रकार है:
\n\nlet str = "Привет, Swift!"\nlet index = str.index(str.startIndex, offsetBy: 2)\nlet char = str[index] // "и"\n\nकाम करता है? हाँ। इष्टतम? नहीं।
\n\nप्रदर्शन की समस्या: offsetBy क्या छिपाता है
\n\nstr.index(startIndex, offsetBy: n) का प्रत्येक कॉल एक O(n) ऑपरेशन है। कल्पना करें कि आपके पास 10,000 कैरेक्टर की एक स्ट्रिंग है, और आप इंडेक्स 9999 पर कैरेक्टर प्राप्त करना चाहते हैं। Swift सही कैरेक्टर खोजने के लिए सभी 9999 कैरेक्टरों से गुज़रेगा। इसे 100 बार लूप में करें? आपको वर्ग जटिलता मिलती है।
यहाँ धीमे कोड का एक उदाहरण है, जो अक्सर शुरुआती लोगों में देखा जाता है:
\n\nlet longString = "A" + String(repeating: "b", count: 10_000) + "C"\nfor i in 0..<longString.count {\n let index = longString.index(longString.startIndex, offsetBy: i)\n let char = longString[index]\n // char के साथ कुछ करें\n}\n\nयह कोड बहुत धीमा चलेगा, क्योंकि offsetBy का प्रत्येक कॉल startIndex से शुरू होता है। वास्तव में जटिलता O(n²) है।
अनुकूलन #1: इंक्रीमेंटल इंडेक्स का उपयोग
\n\nSwift में nth कैरेक्टर प्राप्त करने को गति देने का सबसे सरल तरीका हर बार इंडेक्स को शून्य से पुनर्गणना न करना है। index(after:) या formIndex(after:) का उपयोग करें।
let longString = "A" + String(repeating: "b", count: 10_000) + "C"\nvar index = longString.startIndex\nfor _ in 0..<longString.count {\n let char = longString[index]\n // char के साथ कुछ करें\n index = longString.index(after: index) // O(1)!\n}\n\nअब जटिलता रैखिक O(n) है। लेकिन क्या होगा यदि हमें अनुक्रमिक के बजाय मनमाने इंडेक्स द्वारा पहुँच की आवश्यकता हो?
\n\nअनुकूलन #2: कैरेक्टर सरणी में रूपांतरण (चेतावनियों के साथ)
\n\nयदि आपको बार-बार मनमाने इंडेक्स (nth कैरेक्टर) द्वारा कैरेक्टर तक पहुँचने की आवश्यकता है, और स्ट्रिंग बहुत बड़ी नहीं है, तो इसे [Character] में बदलना सबसे आसान है। तब पहुँच O(1) होगी।
let str = "Привет, Swift!"\nlet chars = Array(str)\nlet char = chars[2] // "и