एनएसएसईटी से एक वस्तु प्राप्त करना


93

यदि आपको ऑब्जेक्ट के साथ ऑब्जेक्ट नहीं मिल सकता है। Indexex: एक NSSet से तो आप ऑब्जेक्ट्स को कैसे पुनः प्राप्त करते हैं?


1
[[nsSetObjects allObjects] objectAtIndex: anyInteger]
मुबीन क़ाज़ी

जवाबों:


139

एक सेट के लिए कई उपयोग के मामले हैं। आप (जैसे enumerateObjectsUsingBlockया NSFastEnumeration के साथ ) के माध्यम से गणना कर सकते हैं , containsObjectसदस्यता के लिए परीक्षण करने के लिए कॉल करें , anyObjectसदस्य प्राप्त करने के लिए उपयोग करें (यादृच्छिक नहीं), या इसे किसी विशेष क्रम में (किसी विशेष क्रम में) सरणी में परिवर्तित करें allObjects

एक सेट उपयुक्त है जब आप डुप्लिकेट नहीं चाहते हैं, आदेश की परवाह नहीं करते हैं, और तेजी से सदस्यता परीक्षण चाहते हैं।


7
आप सेट member:संदेश भेजकर संभावित डुप्लिकेट द्वारा किसी ज्ञात ऑब्जेक्ट को देख सकते हैं । यदि यह वापस लौटता है nil, तो सेट में आपके द्वारा पारित किए गए ऑब्जेक्ट के बराबर वस्तु नहीं होती है; यदि वह ऑब्जेक्ट पॉइंटर लौटाता है, तो वह पॉइंटर लौटाता है जो पहले से ही सेट में मौजूद ऑब्जेक्ट पर है। सेट में वस्तुओं को लागू करना चाहिए hashऔर इसके isEqual:लिए उपयोगी होना चाहिए।
पीटर होसी

@PeterHosey मुझे नहीं लगता कि इसे लागू करने की hash आवश्यकता है; अगर आपने ऐसा किया तो यह बहुत तेजी से आगे बढ़ेगा।
fumoboy007

2
@ fumoboy007: एक सेट में भंडारण के लिए या एक शब्दकोश में एक कुंजी के रूप में उपयोग करने के लिए, हाँ यह करता है। hashNSObject प्रोटोकॉल के प्रलेखन से : "यदि दो वस्तुएं समान हैं (जैसा कि isEqual:विधि द्वारा निर्धारित किया गया है), उनके पास समान हैश मान होना चाहिए।" वर्तमान में, NSObject के कार्यान्वयन hashऔर isEqual:वस्तु की पहचान (पता) का उपयोग करते हैं। यदि आप ओवरराइड करते हैं isEqual:, तो आप उन वस्तुओं की संभावना स्थापित कर रहे हैं जो समान नहीं हैं, लेकिन समान हैं- जो, यदि आप ओवरराइड नहीं करते हैं hash, तो भी अलग-अलग हैश होंगे। यह इस आवश्यकता का उल्लंघन करता है कि समान वस्तुओं में समान हैश है।
पीटर होसी

1
@ fumoboy007: इस बात पर विचार करें कि हैश टेबल कैसे काम करती है: कंटेनर में कुछ संख्या में बाल्टियाँ होती हैं, और प्रत्येक आने वाली वस्तु के हैश का उपयोग यह निर्धारित करने के लिए किया जाता है कि किस बाल्टी में वह वस्तु होनी चाहिए। जैसे कि देखने के लिए member:, कंटेनर केवल उसी में दिखेगा। बकेट (यही वजह है कि सदस्यता परीक्षण में सरणियों की तुलना में सेट बहुत तेज़ होते हैं और शब्दकोष कुंजी-मूल्य लुकअप में समानांतर सरणियों की तुलना में बहुत तेज़ होते हैं)। यदि मांगी जा रही वस्तु में गलत हैश है, तो कंटेनर गलत बाल्टी में दिखेगा, और मैच नहीं मिलेगा।
पीटर होसी

@PeterHosey ओह ... मैंने गलती से सोचा था कि डिफ़ॉल्ट कार्यान्वयन -[NSObject hash]0. था। यह बहुत कुछ समझाता है। = एस
fumoboy007

31

NSSet में कोई विधि नहीं है

सभी ऑबजेक्ट्स को कॉल करने का प्रयास करें, जो सभी ऑब्जेक्ट्स का NSArray लौटाता है।


क्या आपके पास कोई विचार है अगर वापस लौटाए गए सरणी का आदेश दिया गया है? दूसरे शब्दों में, यदि "setByAddingObject" का उपयोग करके सेट में वस्तुओं को जोड़ा जाता है, और मैंने "allObjects" का उपयोग किया है, हैं? मेरे द्वारा ऑब्जेक्ट्स को जोड़ने के क्रम में दिए गए सरणी में तत्व?
IosMentalist

NSSortPredicate के साथ परिणामी सरणी को क्रमबद्ध करें और आप ठीक हो जाएंगे
जेसन

यदि आप केवल एक विशिष्ट वस्तु में रुचि रखते हैं, तो बेहतर फ़िल्टर किए गएSetUsingPredicate दृष्टिकोण का उपयोग करें।
akw

17

यदि आपके पास आवश्यक वस्तु का चयन करने के लिए आपके पास किसी प्रकार का विशिष्ट पहचानकर्ता है, तो फ़िल्टर्डसिटिंगप्र्रेडिकेट का उपयोग करना संभव है।

पहले विधेय बनाएं (ऑब्जेक्ट में आपकी विशिष्ट आईडी को "पहचानकर्ता" कहा जाता है और यह एक NSString है):

NSPredicate *myPredicate = [NSPredicate predicateWithFormat:@"identifier == %@", identifier];

और फिर विधेय का उपयोग करके वस्तु चुनें:

NSObject *myChosenObject = [mySet filteredSetUsingPredicate:myPredicate].anyObject;

13

NSArray *myArray = [myNSSet allObjects];

MyObject *object = [myArray objectAtIndex:(NSUInteger *)]

अपनी इच्छित वस्तु के सूचकांक के साथ NSUInteger को बदलें।


1
होना चाहिए: MyObject * ऑब्जेक्ट = [myArray objectAtIndex: (NSUInteger *)]
जॉन डी।

8

Swift3 और iOS10 के लिए:

//your current set
let mySet : NSSet
//targetted index
let index : Int
//get object in set at index
let object = mySet.allObjects[index]

6

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 के उपयोग को प्राथमिकता देने का एक कारण यह है।



0

अधिकांश समय आप एक सेट से एक विशेष वस्तु प्राप्त करने के बारे में परवाह नहीं करते हैं। आप परीक्षण के बारे में यह देखने के लिए परवाह करते हैं कि किसी सेट में कोई ऑब्जेक्ट है या नहीं। यही सेट के लिए अच्छे हैं। जब आप यह देखना चाहते हैं कि कोई वस्तु संग्रह सेट में है तो सरणियों की तुलना में बहुत तेज है।

यदि आप इस बात की परवाह नहीं करते हैं कि आपको कौन सी वस्तु मिलती है, तो उपयोग करें -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);
}
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.