सिंथेटिक स्विफ्ट मानों को उनके सम्मिलन क्रम को बदले बिना अद्वितीय रखने के लिए, इनपुट सरणी को एक बार स्कैन करें, स्वीकृत कुंजियों को एक सेट में ट्रैक करें, और केवल पहली घटनाओं को आउटपुट सरणी में जोड़ें। यह गाइड एक छोटी स्थानीय गणना बनाती है जिसे आप मैक पर चला सकते हैं।
कार्य सिंथेटिक आकार मानों की एक क्रमबद्ध सूची को संसाधित करना, दोहराए गए मानों को हटाना, और बनाए रखी गई प्रविष्टियों से कुल की गणना करना है। सब कुछ मेमोरी में होता है; उदाहरण कोई बाहरी इनपुट नहीं पढ़ता और कोई गणना परिणाम नहीं सहेजता।
संग्रह चुनने से पहले "अद्वितीय" का अर्थ परिभाषित करें
स्विफ्ट सरणियाँ क्रम को संरक्षित करती हैं और डुप्लिकेट की अनुमति देती हैं। सेट में अद्वितीय मान होते हैं लेकिन उनका कोई परिभाषित क्रम नहीं होता। नतीजतन, एक सरणी को सेट में और फिर वापस सरणी में बदलने से पहली घटना का क्रम संरक्षित नहीं होता। बाद में सॉर्ट करने से एक सॉर्टिंग क्रम स्थापित होता है, जो सम्मिलन क्रम से भिन्न हो सकता है। ये संग्रह व्यवहार स्विफ्ट के संग्रह प्रकार में प्रलेखित हैं।
इस उदाहरण के लिए, प्रत्येक सिंथेटिक मान का एक आकार नाम और एक आकार होता है। डिफ़ॉल्ट अनुबंध दो प्रविष्टियों को डुप्लिकेट मानता है केवल जब दोनों गुण मेल खाते हैं। इसलिए आकार 12 वाला एक वृत्त और आकार 20 वाला एक वृत्त अलग-अलग मान बने रहते हैं।
| अनुबंध प्रश्न | इस गणना के लिए नियम |
|---|---|
| इनपुट क्रम क्या निर्धारित करता है? | आपूर्ति की गई सरणी में स्थिति |
| दो मानों को डुप्लिकेट क्या बनाता है? | समान आकार और समान आकार |
| कौन सी घटना बचती है? | पहली घटना |
| क्या बाद का डुप्लिकेट बनाए रखे गए मान को हिलाता है? | नहीं |
| खाली इनपुट के साथ क्या होता है? | एक खाली सरणी और शून्य का कुल लौटाएं |
| कौन से मान कुल में योगदान करते हैं? | केवल बनाए रखे गए मान |
यह अनुबंध एक आसान गलती को रोकता है: आकार के नाम से प्रविष्टियों को हटाना जब गणना को अलग-अलग आकार-और-आकार संयोजनों की आवश्यकता होती है। कार्य किया गया उदाहरण आकार-मात्र परिणाम की भी गणना करता है ताकि आप उस नियम को बदलने के परिणाम देख सकें।
अपने मैक पर एक पूर्ण स्थानीय स्विफ्ट उदाहरण बनाएं
आपको एक स्थापित स्विफ्ट टूलचेन की आवश्यकता है। Terminal में, swift --version चलाकर पुष्टि करें कि कमांड उपलब्ध है। स्विफ्ट का आधिकारिक कमांड-लाइन टूल बनाएं ट्यूटोरियल उस जांच, निष्पादन योग्य पैकेज निर्माण, और पैकेज चलाने का दस्तावेजीकरण करता है।
उदाहरण के लिए एक नई निर्देशिका बनाएं और एक निष्पादन योग्य पैकेज आरंभ करें:
mkdir OrderDemo
cd OrderDemo
swift package init --name OrderDemo --type executable
Sources के तहत उत्पन्न निष्पादन योग्य स्रोत फ़ाइल को नीचे दिए गए पूर्ण प्रोग्राम से बदलें। उत्पन्न फ़ाइल नाम और निर्देशिका लेआउट टूलचेन के साथ भिन्न हो सकते हैं; इसके मौजूदा प्रवेश बिंदु को बदलें बजाय दूसरा जोड़ने के। यह प्रोग्राम @main प्रवेश बिंदु का उपयोग करता है, इसलिए इसे OrderDemo.swift नाम की फ़ाइल में रखें, यदि आवश्यक हो तो उत्पन्न main.swift का नाम बदलें। स्विफ्ट का कमांड-लाइन ट्यूटोरियल main.swift फ़ाइल और @main प्रवेश बिंदु के बीच चयन की व्याख्या करता है।
कोई आयात या पैकेज निर्भरता आवश्यक नहीं है। प्रोग्राम मानक-पुस्तकालय प्रकारों और फ़ंक्शंस का उपयोग करता है।
struct Tile: Hashable {
let shape: String
let size: Int
}
func uniqueFirst<Value, Key: Hashable>(
_ values: [Value],
by key: (Value) -> Key
) -> [Value] {
var seen: Set<Key> = []
var result: [Value] = []
for value in values {
if seen.insert(key(value)).inserted {
result.append(value)
}
}
return result
}
@main
struct OrderDemo {
static func main() {
let input = [
Tile(shape: "circle", size: 12),
Tile(shape: "square", size: 8),
Tile(shape: "circle", size: 12),
Tile(shape: "circle", size: 20),
Tile(shape: "square", size: 8)
]
let retained = uniqueFirst(input, by: { $0 })
let total = retained.reduce(0) { $0 + $1.size }
let skipped = input.count - retained.count
let expected = [
Tile(shape: "circle", size: 12),
Tile(shape: "square", size: 8),
Tile(shape: "circle", size: 20)
]
precondition(retained == expected)
precondition(total == 40)
precondition(skipped == 2)
let empty: [Tile] = []
precondition(uniqueFirst(empty, by: { $0 }).isEmpty)
precondition(
uniqueFirst([input[0], input[0]], by: { $0 })
== [input[0]]
)
let byShape = uniqueFirst(input, by: { $0.shape })
precondition(byShape == [input[0], input[1]])
let shapeTotal = byShape.reduce(0) { $0 + $1.size }
precondition(shapeTotal == 20)
for tile in retained {
print("\(tile.shape): \(tile.size)")
}
print("Total: \(total)")
print("Skipped duplicates: \(skipped)")
print("Shape-only total: \(shapeTotal)")
}
}
पैकेज निर्देशिका से, चलाएं:
swift run OrderDemo
अपेक्षित प्रोग्राम आउटपुट, किसी भी बिल्ड संदेश के बाद, नीचे दिखाया गया है। प्रोग्राम को पुनर्प्राप्त API प्रलेखन के विरुद्ध निरीक्षण किया गया था लेकिन यहां निष्पादित नहीं किया गया क्योंकि इस शोध वातावरण में कोई स्विफ्ट निष्पादन योग्य नहीं है।
वृत्त: 12
वर्ग: 8
वृत्त: 20
कुल: 40
छोड़े गए डुप्लिकेट: 2
आकार-मात्र कुल: 20
सरणी-और-सेट दृष्टिकोण क्रम को क्यों संरक्षित करता है?
सरणी आउटपुट क्रम का एकमात्र स्रोत है। लूप प्रत्येक इनपुट स्थिति को क्रम में देखता है, और append(_:) एक स्वीकृत मान को परिणाम के अंत में रखता है। सेट केवल इस सवाल का जवाब देता है कि चयनित कुंजी पहले से प्रकट हुई है या नहीं; प्रोग्राम कभी भी इसके ऊपर पुनरावृति नहीं करता।
महत्वपूर्ण अभिव्यक्ति seen.insert(key(value)).inserted है। स्विफ्ट प्रलेखित करता है कि insert(_:) एक नए सदस्य के लिए inserted को true के रूप में लौटाता है और जब एक समान सदस्य पहले से मौजूद होता है तो false। एक मौजूदा सदस्य अपरिवर्तित रहता है। वह वापसी मान एक ऑपरेशन को यह तय करने देता है कि मूल मान को जोड़ना है या नहीं। Apple के सेट सम्मिलन प्रलेखन देखें।
आपूर्ति किए गए इनपुट के लिए, पहला वृत्त और वर्ग स्वीकृत होते हैं। दूसरा समान वृत्त छोड़ दिया जाता है। बड़ा वृत्त स्वीकृत होता है क्योंकि उसका पूर्ण मान भिन्न होता है, और दोहराया गया वर्ग छोड़ दिया जाता है। इसलिए बनाए रखे गए आकार 12 + 8 + 20 = 40 हैं।
कार्यान्वयन एक उपयोगी अपरिवर्तनीयता बनाए रखता है: प्रत्येक पुनरावृत्ति के बाद, परिणाम में seen में हर कुंजी के लिए सबसे पहले मिला मान होता है, मुठभेड़ क्रम में। एक नई कुंजी दोनों संग्रहों को विस्तारित करती है; एक दोहराई गई कुंजी किसी को नहीं बदलती। यह तर्क सेट द्वारा अपने सदस्यों को संग्रहीत करने के तरीके से स्वतंत्र रूप से क्रम गारंटी की व्याख्या करता है।
कस्टम स्विफ्ट मान समानता कैसे व्यक्त करें?
घोषणा struct Tile: Hashable संश्लेषित अनुरूपता का अनुरोध करती है। दोनों संग्रहीत गुण, String और Int, हैशेबल हैं, इसलिए स्विफ्ट आवश्यक व्यवहार को संश्लेषित कर सकता है। Apple इन संश्लेषण शर्तों को Hashable में प्रलेखित करता है।
{ $0 } को कुंजी के रूप में उपयोग करना पूरे Tile मान को विशिष्टता निर्धारित करने के लिए बनाता है। { $0.shape } का उपयोग अनुबंध को प्रति आकार एक बनाए रखी गई प्रविष्टि में बदल देता है। उदाहरण में, यह बाद में आकार 20 के वृत्त को हटा देता है, कुल को 20 तक कम कर देता है। यह दो नियमों के बीच एक जानबूझकर तुलना है, एक ही नियम का दूसरा कार्यान्वयन नहीं।
गणना की अवधि के लिए कुंजी चयन को नियतात्मक रखें। इसे संसाधित किए जा रहे मान से प्राप्त करें न कि काउंटर या बदलते बाहरी चर से। अन्यथा, समान इनपुट को अलग-अलग कुंजियाँ प्राप्त हो सकती हैं और अलग प्रविष्टियों के रूप में जीवित रह सकती हैं।
यदि आप मैन्युअल रूप से समानता और हैशिंग लागू करते हैं, तो दोनों में मिलान करने वाले आवश्यक गुणों का उपयोग करें। Apple को समान उदाहरणों की आवश्यकता है कि वे हैशर में समान क्रम में समान मान खिलाएं। hashValue को स्वयं विशिष्टता कुंजी के रूप में उपयोग करने से बचें: एक हैश मान के समानता अनुबंध का विकल्प नहीं है। वास्तविक हैशेबल कुंजी को रखने से सेट को उस अनुबंध को लागू करने की अनुमति मिलती है। Hashable की अनुरूपता आवश्यकताएँ देखें।
आपको क्रमबद्ध संग्रह का उपयोग कब करना चाहिए?
इस एकल गणना के लिए, एक सरणी प्लस एक स्थानीय सेट व्यवहार को स्पष्ट रखता है। यदि कोई एप्लिकेशन बार-बार जोड़ता है, हटाता है, पुनः क्रमित करता है, और अद्वितीय सदस्यों को क्वेरी करता है, तो एक समर्पित क्रमबद्ध संग्रह उन कार्यों को बनाए रखना आसान बना सकता है।
| विकल्प | उपयुक्त स्थिति | प्रासंगिक सीमा |
|---|---|---|
| सरणी प्लस सेट | सिंथेटिक स्विफ्ट मानों पर एक पास, संभवतः चयनित कुंजी का उपयोग करके | आपका फ़ंक्शन पहली-घटना व्यवहार को परिभाषित करता है |
स्विफ्ट कलेक्शंस OrderedSet |
अद्वितीय हैशेबल मानों के क्रमबद्ध संग्रह का चल रहा उपयोग | अलग स्विफ्ट कलेक्शंस पैकेज की आवश्यकता होती है |
फाउंडेशन NSOrderedSet |
एक API पहले से फाउंडेशन क्रमबद्ध ऑब्जेक्ट संग्रह के साथ काम करता है | एक वर्ग जो स्थिर क्रमबद्ध संग्रह का प्रतिनिधित्व करता है; परिवर्तनीय संचालन NSMutableOrderedSet का उपयोग करते हैं |
आधिकारिक स्विफ्ट कलेक्शंस प्रलेखन OrderedSet को अद्वितीय तत्वों के क्रमबद्ध संग्रह के रूप में वर्णित करता है, जिसे OrderedCollections के माध्यम से आयात किया जाता है। यह append(_:) और insert(_:at:) जैसे स्थिति-जागरूक संचालन प्रदान करता है। वे पैकेज API हैं, इसलिए केवल import OrderedCollections जोड़ने से अन्यथा निर्भरता-मुक्त प्रोजेक्ट कॉन्फ़िगर नहीं होता। OrderedSet देखें।
Apple का फाउंडेशन प्रलेखन NSOrderedSet को विशिष्ट वस्तुओं के स्थिर क्रमबद्ध संग्रह के रूप में वर्णित करता है और NSMutableOrderedSet को इसके परिवर्तनीय समकक्ष के रूप में पहचानता है। ऊपर दी गई देशी स्विफ्ट मान गणना के लिए, जेनेरिक फ़ंक्शन चुनी गई समानता कुंजी को सीधे व्यक्त करता है बिना उस ऑब्जेक्ट संग्रह को पेश किए। NSOrderedSet देखें।
जब गणना डेस्कटॉप इंटरफ़ेस को खिलाती है तो क्या बदलता है?
पूर्ण उदाहरण सिंक्रोनस है और फ़ंक्शन के अंदर अपने अस्थायी संग्रहों का मालिक है। एक छोटी सिंथेटिक सूची के लिए, यह कार्यों को पेश किए बिना एक स्पष्ट प्रसंस्करण क्रम देता है।
macOS इंटरफ़ेस में, UI-सामना करने वाले स्थिति और अपडेट को उचित रूप से अलग करें। Apple MainActor को एक वैश्विक अभिनेता के रूप में प्रलेखित करता है जिसका एक्ज़ीक्यूटर मुख्य डिस्पैच कतार के बराबर है; स्विफ्ट का समवर्ती गाइड @MainActor को उन फ़ंक्शंस और प्रकारों पर लागू करने की व्याख्या करता है जो इंटरफ़ेस स्थिति का उपयोग करते हैं। MainActor और समवर्तिता देखें।
समवर्तिता के लिए क्रम की एक स्पष्ट परिभाषा की भी आवश्यकता होती है। स्विफ्ट एक टास्क समूह में चाइल्ड टास्क के पूर्ण होने के क्रम की गारंटी नहीं देता। परिणामों को टास्क के पूरा होने पर जोड़ने से इसलिए पूर्णता क्रम संरक्षित होता है, जो मूल इनपुट क्रम से भिन्न हो सकता है। आधिकारिक समवर्तिता गाइड इस सीमा का दस्तावेजीकरण करता है।
यदि कोई भविष्य का संस्करण स्वतंत्र सिंथेटिक गणनाओं को समवर्ती रूप से करता है, तो प्रत्येक इनपुट स्थिति को उसके परिणाम के साथ ले जाएं, संग्रह के बाद इनपुट-स्थिति क्रम को बहाल करें, और फिर विशिष्टता पास लागू करें। यह उस प्रलेखित पूर्णता-क्रम सीमा से प्राप्त एक डिज़ाइन है। जब तक अतिरिक्त कार्य अतिरिक्त समन्वय को उचित नहीं ठहराता, वर्तमान छोटे उदाहरण को सिंक्रोनस रखें।
फ़ंक्शन का पुन: उपयोग करने से पहले अनुबंध की जांच करें
प्रोग्राम में सटीक बनाए रखे गए क्रम, खाली इनपुट, दोहराए गए समान मानों, और वैकल्पिक आकार-मात्र नियम के लिए जांच शामिल हैं। ये जांच उन निर्णयों को लक्षित करती हैं जो गणना के अर्थ को बदलने की सबसे अधिक संभावना रखते हैं।
इसे अनुकूलित करते समय, तीन शर्तों की जांच करें: इनपुट में पहले से ही एक सार्थक क्रम होना चाहिए, कुंजी को आपके इच्छित समानता नियम को व्यक्त करना चाहिए, और पहली घटना को बनाए रखना उचित होना चाहिए। फ़ंक्शन जानबूझकर बाद की मिलान वाली प्रविष्टियों को छोड़ देता है; यह न तो उनके आकारों को मर्ज करता है और न ही बनाए रखे गए मान को प्रतिस्थापित करता है। रिपोर्ट की गई छोड़ी गई गिनती उस प्रभाव को दृश्यमान बनाती है।
आपूर्ति की गई सिंथेटिक आकार सूची के लिए, तैयार परिणाम पहली-घटना क्रम में तीन मान और 40 का कुल है। सरणी को क्रम के लिए जिम्मेदार रखें, सेट को सदस्यता के लिए जिम्मेदार रखें, और चयनित कुंजी को "अद्वितीय" का अर्थ निर्धारित करने के लिए जिम्मेदार रखें।
स्रोत
- संग्रह प्रकार — द स्विफ्ट प्रोग्रामिंग लैंग्वेज, स्विफ्ट प्रोजेक्ट।
- कमांड-लाइन टूल बनाएं — Swift.org।
- insert(_:) — Apple डेवलपर प्रलेखन।
- Hashable — Apple डेवलपर प्रलेखन।
- OrderedSet — Apple, स्विफ्ट कलेक्शंस।
- NSOrderedSet — Apple डेवलपर प्रलेखन।
- MainActor — Apple डेवलपर प्रलेखन।
- समवर्तिता — द स्विफ्ट प्रोग्रामिंग लैंग्वेज, स्विफ्ट प्रोजेक्ट।