2009-08-30 19 views
8

मेरे पास अद्वितीय पूर्णांक कुंजी के आधार पर डेटासेट के लिए एक अनिश्चित आकार है।कोको में स्पैस सरणी कैसे करें

मैं तेजी से लुकअप के लिए NSMutableArray का उपयोग करना चाहता हूं क्योंकि मेरी सभी कुंजी पूर्णांक आधारित हैं।

मैं यह करना चाहता हूं।

NSMutableArray* data = [NSMutableArray array]; // just create with 0 size 

फिर बाद में लोगों पूर्णांक अनुक्रमित (सभी अद्वितीय) के साथ मुझे डेटा फेंकने शुरू कर देंगे तो मैं बस कुछ इस तरह करना चाहते हैं ...

if ([data count] < index) 
    [data resize:index]; // ? how do you resize 

और सरणी ताकि आकार दिया है मैं तो कर सकते हैं ...

[data insertObject:obj atIndex:index]; 

अंतिम आकार और नए आकार के बीच सभी स्लॉट शून्य के साथ अंततः बाद में भर जाएगा।

तो मेरा सवाल यह है कि मैं मौजूदा NSMutableArray का आकार कैसे बदलूं?

धन्यवाद, रोमन

उत्तर

17

ऐसा लगता है कि अपनी आवश्यकताओं बेहतर एक NSMutableDictionary के साथ मुलाकात की जाएगी। आप इस प्रकार NSNumber वस्तुओं में int रों रैप करने के लिए की आवश्यकता होगी:

-(void)addItem:(int)key value:(id)obj 
{ 
    [data setObject:obj forKey:[NSNumber numberWithInt:key]]; 
} 

-(id)getItem:(int)key 
{ 
    return [data objectForKey:[NSNumber numberWithInt:key]]; 
} 

वहाँ कोई आसान एक NSMutableArray का आकार बड़ा करने के लिए था, क्योंकि आप में वस्तुओं के बराबर नहीं हो सकता है के बीच स्लॉट। हालांकि, आप एक स्पैर सरणी की उपस्थिति बनाने के लिए 'filler' के रूप में [NSNull null] का उपयोग कर सकते हैं।

+0

त्वरित उत्तर के लिए धन्यवाद। मैं लगातार लुकअप के समय की उम्मीद कर रहा था लेकिन यह बहुत बुरा नहीं है। उम्मीद है कि मेरे डेटासेट आकार बहुत बड़े नहीं होंगे। धन्यवाद। –

+0

एक शब्दकोश हैशसेट है, यह निरंतर समय लुकअप का समर्थन करता है। – twolfe18

+0

आह! मैं नहीं जानता था कि। मुझे लगता है कि यह लॉग था (एन)। जानकारी के लिए धन्यवाद। –

33

एक NSPointerArray का उपयोग करें।

http://developer.apple.com/mac/library/documentation/Cocoa/Reference/Foundation/Classes/NSPointerArray_Class/Introduction/Introduction.html

NSPointerArray एक परिवर्तनशील संग्रह NSArray के बाद मॉडलिंग की है लेकिन यह भी शून्य मान है, जो हो सकता है कर सकते हैं डाला जाता है या निकाले (और जो वस्तु की गिनती करने के लिए योगदान)। इसके अलावा, पारंपरिक सरणी के विपरीत, आप सीधे सरणी की गणना सेट कर सकते हैं। एक कचरे में पर्यावरण एकत्रित किया गया है, यदि आप शून्यकमजोर स्मृति कॉन्फ़िगरेशन निर्दिष्ट करते हैं, तो तत्व एकत्रित किया जाता है तो इसे द्वारा एक पूर्ण मान प्रतिस्थापित किया जाता है।

यदि आप समाधान जैसे शब्दकोश का उपयोग करना चाहते हैं, तो NSMapTable का उपयोग करें। यह पूर्णांक कुंजी की अनुमति देता है। एनएसएमयूटेबल डिक्शनरी समाधान की सिफारिश की गई है कि सभी मुक्केबाजी & पूर्णांक कुंजी के अनबॉक्सिंग से संबंधित भारी मात्रा में ओवरहेड है।

+1

एक 'NSPointerArray' एक स्पैस सरणी नहीं है, और न ही यह एक जैसा व्यवहार करता है। आपको अभी भी सभी अप्रयुक्त इंडेक्स को 'न्यूल' पॉइंटर्स से भरना होगा। आउटपुट से '[पॉइंटरएरे डालने सूचक: @ "परीक्षण" पर इंडेक्स: 17];' ताजा तत्काल 'एनएसपीइंटरएरे' पर; '*** अपरिपक्व अपवाद के कारण ऐप को समाप्त करना 'एनएसआईएनवालिडअर्ग्यूमेंट एक्सेप्शन', कारण: '*** - [एनएससीओनकॉन्टरएर्रे डालने वाला पॉइंटर: atIndex:]: सूचकांक 17 पर पॉइंटर डालने का प्रयास सीमा 0 से – johne

+3

यह गलत है। आप कॉल -सेट कॉल करने में विफल रहे: क्षमता को पर्याप्त आकार में सेट करने के लिए। – bbum

+6

ध्यान दें कि आईएसओ में NSPointerArray उपलब्ध नहीं है। –

-4

मुझे इस पर बीबीएम के जवाब से असहमत होना है। एक NSPointerArray एक सरणी है, न कि एक स्पैस सरणी है, और दोनों के बीच महत्वपूर्ण अंतर हैं।

मैं दृढ़ता से अनुशंसा करते हैं कि bbums समाधान न किया जाए।

NSPointerArray के लिए प्रलेखन here उपलब्ध है।

कोको में पहले से ही एक सरणी वस्तु है जैसा कि NSArray वर्ग द्वारा परिभाषित किया गया है। NSPointerArrayNSObject से विरासत में है, इसलिए यह NSArray का प्रत्यक्ष उप-वर्ग नहीं है। हालांकि, NSPointerArray प्रलेखन जैसे वर्ग की परिभाषा:

NSPointerArray is a mutable collection modeled after NSArray but it can also hold NULL values

मैं प्रलेखन से इस परिभाषा का दावा है कि यह है कि इस NSArray की एक "तार्किक" उपवर्ग है स्वयंसिद्ध धारणा कर देगा।

परिभाषाएं

एक "सामान्य" सरणी है: आइटम का संग्रह, जिनमें से प्रत्येक के साथ जुड़े एक अद्वितीय सूचकांक संख्या है।

योग्यता के बिना एक सरणी है: एक "सामान्य" सरणी जहां वस्तुओं की अनुक्रमणिका निम्नलिखित गुण हैं: सरणी में वस्तुओं के लिए इंडेक्स 0 से शुरू होते हैं और अनुक्रमिक रूप से बढ़ते हैं। सरणी में सभी वस्तुओं में सरणी में आइटम्स की संख्या से कम सूचकांक संख्या होती है। किसी सरणी में कोई आइटम जोड़ना सरणी में अंतिम आइटम के इंडेक्स + 1 पर होना चाहिए, या किसी आइटम को दो मौजूदा आइटम इंडेक्स नंबरों के बीच डाला जा सकता है, जिसके कारण सभी बाद की वस्तुओं की इंडेक्स संख्या एक से बढ़ाई जा सकती है। किसी मौजूदा इंडेक्स नंबर पर एक आइटम को किसी अन्य आइटम द्वारा प्रतिस्थापित किया जा सकता है और यह ऑपरेशन मौजूदा परिचालनों की अनुक्रमणिका संख्याओं को नहीं बदलता है। इसलिए, दो अलग-अलग संचालन डालें और बदलें।

एक स्पैस सरणी है: एक "सामान्य" सरणी जहां पहले आइटम का इंडेक्स नंबर किसी भी नंबर पर शुरू हो सकता है और सरणी में जोड़े गए बाद की वस्तुओं की इंडेक्स संख्या का कोई अन्य संबंध नहीं है या प्रतिबंध अन्य नियमों के आधार पर नहीं है सरणी। किसी स्पैस सरणी में किसी आइटम को डालने से सरणी में अन्य आइटम्स की अनुक्रमणिका संख्या प्रभावित नहीं होती है। किसी आइटम को सम्मिलित करना और किसी आइटम को प्रतिस्थापित करना आमतौर पर अधिकांश कार्यान्वयन में समानार्थी होता है। स्पैस सरणी में वस्तुओं की संख्या की गिनती स्पैस सरणी में आइटम्स की इंडेक्स संख्याओं से कोई संबंध नहीं है।

ये परिभाषाएं "ब्लैक बॉक्स" सरणी के व्यवहार के बारे में कुछ भविष्यवाणियां करती हैं जो परीक्षण योग्य हैं। सादगी के लिए, हम निम्नलिखित संबंधों पर ध्यान केंद्रित करेंगे:

एक सरणी में, सरणी में सभी वस्तुओं की अनुक्रमणिका संख्या सरणी में आइटम्स की संख्या की गणना से कम है। हालांकि यह एक स्पैस सरणी के बारे में सच हो सकता है, यह एक आवश्यकता नहीं है।

bbum के लिए एक टिप्पणी में, मैं निम्नलिखित ने कहा:

एक NSPointerArray एक विरल सरणी नहीं है, न ही यह एक की तरह व्यवहार करता है। आपको अभी भी सभी अप्रयुक्त अनुक्रमणिका को NULL पॉइंटर्स से भरना होगा। एक ताजा NSPointerArray instantiated पर [pointerArray insertPointer:@"test" atIndex:17]; से आउटपुट:

*** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '*** -[NSConcretePointerArray insertPointer:atIndex:]: attempt to insert pointer at index 17 beyond bounds 0'

यह कहा गया है, साबित बिना, NSPointerArray के व्यवहार के ऊपर एक विरल सरणी की परिभाषा का उल्लंघन करती है। त्रुटि संदेश का यह हिस्सा खुलासा कर रहा है: attempt to insert pointer at index 17 beyond bounds 0', विशेष रूप से सूचकांक 0 पर पहली नई वस्तु जोड़ने के बारे में हिस्सा।

bbum तो टिप्पणियाँ:

यह गलत है। आप कॉल -सेट कॉल करने में विफल रहे: क्षमता को पर्याप्त आकार में सेट करने के लिए।

यह है गैर sensical एक विरल सरणी में आइटम की संख्या की "गिनती सेट" करने के लिए। यदि NSPointerArray एक स्पैस सरणी थी, तो कोई उम्मीद करेगा कि इंडेक्स 17 पर पहला आइटम जोड़ने के बाद, NSPointerArray में आइटमों की संख्या की गणना एक होगी। हालांकि, बीबीएमएस सलाह के बाद, पहले आइटम जोड़ने के बाद NSPointerArray में आइटमों की संख्या 18 है, 1 नहीं है।

QED- यह दिखाया गया है कि NSPointerArray वास्तव में एक सरणी है, और इस चर्चा के प्रयोजनों के लिए, NSArray

साथ ही, bbum निम्नलिखित अतिरिक्त टिप्पणी करता है:

NSPointerArray सबसे निश्चित रूप से समर्थन छेद करता है।

यह साबित रूप से झूठा है। एक सरणी में इसमें शामिल सभी वस्तुओं की आवश्यकता होती है, भले ही वह कुछ 'कुछ नहीं' हो। यह एक स्पैस सरणी के बारे में सच नहीं है। इस चर्चा के प्रयोजनों के लिए यह 'छेद' की परिभाषा है। एक NSPointerArray में शब्द की स्पैस सरणी भावना में holes शामिल नहीं है।

वह कक्षा लिखने के पूरे बिंदुओं में से एक था। आपको पहले गिनती सेट करनी होगी।

यह एक स्पैस सरणी के "गिनती सेट" के लिए असंभव है।

चाहे आंतरिक कार्यान्वयन एक स्पैस सरणी है या हैश या, आदि एक कार्यान्वयन विस्तार है।

यह सच है। हालांकि, NSPointerArray के लिए प्रलेखन इस बात का कोई भी संदर्भ नहीं देता है कि यह आइटमों की अपनी सरणी को कैसे लागू या प्रबंधित करता है। इसके अलावा, यह कहीं भी नहीं बताता है कि NSPointerArray "कुशलतापूर्वक NULL पॉइंटर्स की एक सरणी प्रबंधित करता है।"

QED- bbum अप्रलेखित व्यवहार कि एक NSPointerArray कुशलता से आंतरिक रूप से एक विरल सरणी के माध्यम से NULL संकेत संभालती है पर निर्भर करता है। होने के कारण अनियंत्रित व्यवहार, यह व्यवहार किसी भी समय बदल सकता है, या NSPointerArray के सभी उपयोगों पर भी लागू नहीं हो सकता है। इस व्यवहार में एक बदलाव आपदा होगा यदि इसमें संग्रहीत उच्चतम सूचकांक संख्या पर्याप्त रूप से बड़ी (~ 2^26) है।

और, वास्तव में, यह स्मृति के एक बड़े हिस्से के रूप में लागू नहीं किया गया है ...

फिर, यह एक निजी कार्यान्वयन विस्तार है कि है अप्रलेखित है। यह अत्यंत खराब प्रोग्रामिंग अभ्यास इस प्रकार के व्यवहार पर निर्भर करता है।

+4

के बाद से आईओएस उपलब्ध है, मैं यहां एक अंग पर बाहर निकलने जा रहा हूं और सुझाव देता हूं कि बीबीएम एनएसपीइंटरएरे को एक स्पैस सरणी के रूप में वर्णित करता है क्योंकि उसके पास पहले से ही यह जानकारी है कि इसे कैसे कार्यान्वित किया गया है। – NSResponder

+6

* मैं स्वैच्छिक धारणा कर दूंगा कि दस्तावेज़ीकरण से यह परिभाषा यह कहती है कि यह एनएसएआरएआरई का "तार्किक" सबक्लास है। * यह एक गलत धारणा होगी। – bbum

+1

हम NSPointerArray के लिए एक सरल श्रेणी जोड़कर इस तर्क को व्यवस्थित नहीं कर सका: @implementation NSPointerArray (HHAdditions) - (शून्य) setPointer: (शून्य *) आइटम atIndex: (NSUInteger) सूचकांक { \t if (! (सूचकांक <[स्वयं गिनती])) { \t \t [स्वयं सेटकाउंट: (अनुक्रमणिका + 1)]; \t} \t \t [self replacePointerAtIndex: सूचकांक के साथ सूचकांक: आइटम]; } @end अब गणना स्वचालित रूप से सेट हो जाती है। वस्तुओं को स्थानांतरित करने के बजाय प्रतिस्थापित किया जाता है। –

1

जेसन के जवाब में, एक एनएसएमयूटेबल डिक्शनरी सबसे अच्छा तरीका प्रतीत होता है। यह एनएसएनबर्स से और उसके सूचकांक मूल्यों को बदलने का ओवरहेड जोड़ता है, लेकिन यह एक क्लासिक स्पेस/टाइम ट्रेड ऑफ है।

मेरे कार्यान्वयन में मैंने स्पैस सरणी को अधिक सरल बनाने के लिए एक एनएसआईएंडएक्ससेट भी शामिल किया।

https://github.com/LavaSlider/DSSparseArray

संबंधित मुद्दे