जवाबों:
एक सेट के लिए कई उपयोग के मामले हैं। आप (जैसे enumerateObjectsUsingBlock
या NSFastEnumeration के साथ ) के माध्यम से गणना कर सकते हैं , containsObject
सदस्यता के लिए परीक्षण करने के लिए कॉल करें , anyObject
सदस्य प्राप्त करने के लिए उपयोग करें (यादृच्छिक नहीं), या इसे किसी विशेष क्रम में (किसी विशेष क्रम में) सरणी में परिवर्तित करें allObjects
।
एक सेट उपयुक्त है जब आप डुप्लिकेट नहीं चाहते हैं, आदेश की परवाह नहीं करते हैं, और तेजी से सदस्यता परीक्षण चाहते हैं।
member:
संदेश भेजकर संभावित डुप्लिकेट द्वारा किसी ज्ञात ऑब्जेक्ट को देख सकते हैं । यदि यह वापस लौटता है nil
, तो सेट में आपके द्वारा पारित किए गए ऑब्जेक्ट के बराबर वस्तु नहीं होती है; यदि वह ऑब्जेक्ट पॉइंटर लौटाता है, तो वह पॉइंटर लौटाता है जो पहले से ही सेट में मौजूद ऑब्जेक्ट पर है। सेट में वस्तुओं को लागू करना चाहिए hash
और इसके isEqual:
लिए उपयोगी होना चाहिए।
hash
आवश्यकता है; अगर आपने ऐसा किया तो यह बहुत तेजी से आगे बढ़ेगा।
hash
NSObject प्रोटोकॉल के प्रलेखन से : "यदि दो वस्तुएं समान हैं (जैसा कि isEqual:
विधि द्वारा निर्धारित किया गया है), उनके पास समान हैश मान होना चाहिए।" वर्तमान में, NSObject के कार्यान्वयन hash
और isEqual:
वस्तु की पहचान (पता) का उपयोग करते हैं। यदि आप ओवरराइड करते हैं isEqual:
, तो आप उन वस्तुओं की संभावना स्थापित कर रहे हैं जो समान नहीं हैं, लेकिन समान हैं- जो, यदि आप ओवरराइड नहीं करते हैं hash
, तो भी अलग-अलग हैश होंगे। यह इस आवश्यकता का उल्लंघन करता है कि समान वस्तुओं में समान हैश है।
member:
, कंटेनर केवल उसी में दिखेगा। बकेट (यही वजह है कि सदस्यता परीक्षण में सरणियों की तुलना में सेट बहुत तेज़ होते हैं और शब्दकोष कुंजी-मूल्य लुकअप में समानांतर सरणियों की तुलना में बहुत तेज़ होते हैं)। यदि मांगी जा रही वस्तु में गलत हैश है, तो कंटेनर गलत बाल्टी में दिखेगा, और मैच नहीं मिलेगा।
-[NSObject hash]
0. था। यह बहुत कुछ समझाता है। = एस
NSSet में कोई विधि नहीं है
सभी ऑबजेक्ट्स को कॉल करने का प्रयास करें, जो सभी ऑब्जेक्ट्स का NSArray लौटाता है।
यदि आपके पास आवश्यक वस्तु का चयन करने के लिए आपके पास किसी प्रकार का विशिष्ट पहचानकर्ता है, तो फ़िल्टर्डसिटिंगप्र्रेडिकेट का उपयोग करना संभव है।
पहले विधेय बनाएं (ऑब्जेक्ट में आपकी विशिष्ट आईडी को "पहचानकर्ता" कहा जाता है और यह एक NSString है):
NSPredicate *myPredicate = [NSPredicate predicateWithFormat:@"identifier == %@", identifier];
और फिर विधेय का उपयोग करके वस्तु चुनें:
NSObject *myChosenObject = [mySet filteredSetUsingPredicate:myPredicate].anyObject;
Swift3 और iOS10 के लिए:
//your current set
let mySet : NSSet
//targetted index
let index : Int
//get object in set at index
let object = mySet.allObjects[index]
NSSet विधि का उपयोग करता है: यह वह है: (जो ऑब्जेक्ट आपके द्वारा उस सेट में डाला गया है, इसके अलावा, यह निर्धारित करने के लिए कि कोई वस्तु उसके अंदर है, ओवरराइड करना चाहिए)।
उदाहरण के लिए, यदि आपके पास एक डेटा मॉडल है जो एक आईडी मान द्वारा इसकी विशिष्टता को परिभाषित करता है (संपत्ति है:
@property NSUInteger objectID;
उसके बाद आप लागू करेंगे:
- (BOOL)isEqual:(id)object
{
return (self.objectID == [object objectID]);
}
और आप हैश लागू कर सकते हैं:
- (NSUInteger)hash
{
return self.objectID; // to be honest, I just do what Apple tells me to here
// because I've forgotten how Sets are implemented under the hood
}
फिर, आप उस आईडी के साथ एक वस्तु प्राप्त कर सकते हैं (साथ ही यह जांच कर सकते हैं कि यह एनएसएसईटी में है):
MyObject *testObject = [[MyObject alloc] init];
testObject.objectID = 5; // for example.
// I presume your object has more properties which you don't need to set here
// because it's objectID that defines uniqueness (see isEqual: above)
MyObject *existingObject = [mySet member: testObject];
// now you've either got it or existingObject is nil
लेकिन हाँ, एक एनएसएसईटी से बाहर निकलने का एकमात्र तरीका यह है कि वह विचार करे जो पहले स्थान पर अपनी विशिष्टता को परिभाषित करता है।
मैंने परीक्षण नहीं किया है कि क्या तेज़ है, लेकिन मैं गणन का उपयोग करने से बचता हूं क्योंकि सदस्य का उपयोग करते समय यह रैखिक हो सकता है: विधि बहुत तेज़ होगी। NSArray के बजाय NSSet के उपयोग को प्राथमिकता देने का एक कारण यह है।
for (id currentElement in mySet)
{
// ** some actions with currentElement
}
अधिकांश समय आप एक सेट से एक विशेष वस्तु प्राप्त करने के बारे में परवाह नहीं करते हैं। आप परीक्षण के बारे में यह देखने के लिए परवाह करते हैं कि किसी सेट में कोई ऑब्जेक्ट है या नहीं। यही सेट के लिए अच्छे हैं। जब आप यह देखना चाहते हैं कि कोई वस्तु संग्रह सेट में है तो सरणियों की तुलना में बहुत तेज है।
यदि आप इस बात की परवाह नहीं करते हैं कि आपको कौन सी वस्तु मिलती है, तो उपयोग करें -anyObject
जो आपको सेट से एक वस्तु देता है, जैसे कि अपना हाथ एक बैग में रखना और किसी चीज़ को हथियाना।
Dog *aDog = [dogs anyObject]; // dogs is an NSSet of Dog objects
यदि आप इस बात की परवाह करते हैं कि आपको कौन सी वस्तु मिलती है, तो उपयोग करें -member
जो आपको वस्तु वापस देती है, या यदि यह सेट में नहीं है तो शून्य करें। आपके पास कॉल करने से पहले ही आपके पास ऑब्जेक्ट होना चाहिए।
Dog *spot = [Dog dogWithName:@"Spot"];
// ...
Dog *aDog = [dogs member:spot]; // Returns the same object as above
यहाँ कुछ कोड है जिसे आप अधिक समझने के लिए Xcode में चला सकते हैं
NSString *one = @"One";
NSString *two = @"Two";
NSString *three = @"Three";
NSSet *set = [NSSet setWithObjects:one, two, three, nil];
// Can't use Objective-C literals to create a set.
// Incompatible pointer types initializing 'NSSet *' with an expression of type 'NSArray *'
// NSSet *set = @[one, two, three];
NSLog(@"Set: %@", set);
// Prints looking just like an array but is actually not in any order
//Set: {(
// One,
// Two,
// Three
// )}
// Get a random object
NSString *random = [set anyObject];
NSLog(@"Random: %@", random); // Random: One
// Iterate through objects. Again, although it prints in order, the order is a lie
for (NSString *aString in set) {
NSLog(@"A String: %@", aString);
}
// Get an array from the set
NSArray *array = [set allObjects];
NSLog(@"Array: %@", array);
// Check for an object
if ([set containsObject:two]) {
NSLog(@"Set contains two");
}
// Check whether a set contains an object and return that object if it does (nil if not)
NSString *aTwo = [set member:two];
if (aTwo) {
NSLog(@"Set contains: %@", aTwo);
}
[[nsSetObjects allObjects] objectAtIndex: anyInteger]