NSArray में रैंडम ऑब्जेक्ट चुनना


83

कहो कि मेरे पास ऑब्जेक्ट्स के साथ एक सरणी है, 1, 2, 3 और 4. मैं इस सरणी से यादृच्छिक ऑब्जेक्ट कैसे चुनूंगा?


यहाँ सभी उत्तर सही हैं, लेकिन अधिक अद्यतित समाधान के लिए मेरा उत्तर यहाँ देखें । यह arc4random_uniformmodulo पूर्वाग्रह से बचने के लिए विधि का उपयोग करता है ।
एडम

इस सवाल का जवाब नहीं है, लेकिन एक दिलचस्प बिंदु - अन्य फाउंडेशन संग्रह (NSSet NSHashTable) में "anyObject" तरीके हैं जो सेट / हैशटेबल से एक मनमाना (यादृच्छिक) ऑब्जेक्ट पढ़ते हैं। नीचे दिए गए सुझावों के अनुसार, NSArray के विस्तार में इस विधि को लागू किया जा सकता है।
मोटी शन्नोर

जवाबों:


192

@ डैरिल का जवाब सही है, लेकिन कुछ मामूली ट्विक्स का इस्तेमाल कर सकते हैं:

NSUInteger randomIndex = arc4random() % theArray.count;

संशोधन:

  • arc4random()ओवर का उपयोग करना rand()और random()सरल है क्योंकि इसमें सीडिंग (कॉलिंग srand()या srandom()) की आवश्यकता नहीं होती है ।
  • सापेक्ष ऑपरेटर ( %), समग्र बयान में कम है, जबकि यह भी अर्थ की दृष्टि से स्पष्ट हो जाता है।

27
Arc4random man पेज से: arc4random_uniform () को ʻarc4random ()% ऊपरी_बाउंड 'जैसे निर्माणों की सिफारिश की जाती है क्योंकि यह "modulo bias" से बचा जाता है जब ऊपरी सीमा दो की शक्ति नहीं होती है।
अधिकतम याँकोव

@collibhoy नहीं है, क्योंकि 0 % 4 = 0, 1 % 4 = 1, 2 % 4 = 2, 3 % 4 = 3, 4 % 4 = 0, 5 % 4 = 1... आप द्वारा सापेक्ष हैं n , अपने सबसे बड़े परिणाम से अधिक होना कभी नहीं होगा n-1
डेव डोंगलांग

1
@DaveDeLong स्रोत कोड के अनुसार, countएक संपत्ति है:@interface NSArray<__covariant ObjectType> : NSObject <NSCopying, NSMutableCopying, NSSecureCoding, NSFastEnumeration> @property (readonly) NSUInteger count;
mikeho

17

यह सबसे सरल उपाय है जिसे मैं लेकर आ सकता हूं:

id object = array.count == 0 ? nil : array[arc4random_uniform(array.count)];

यह जांच करने के लिए आवश्यक है count, क्योंकि एक गैर nilलेकिन खाली NSArrayवापस आ जाएगी 0के लिए count, और arc4random_uniform(0)रिटर्न 0। तो चेक के बिना, आप सरणी पर सीमा से बाहर जाएंगे।

यह समाधान लुभावना है लेकिन गलत है क्योंकि यह एक खाली सरणी के साथ दुर्घटना का कारण होगा:

id object = array[arc4random_uniform(array.count)];

संदर्भ के लिए, यहां दस्तावेज है :

u_int32_t
arc4random_uniform(u_int32_t upper_bound);

arc4random_uniform() will return a uniformly distributed random number less than upper_bound.

मैन पेज में उल्लेख नहीं किया गया है कि जब arc4random_uniformरिटर्न पास किया जाता है ।00upper_bound

इसके अलावा, arc4random_uniformमें परिभाषित किया गया है <stdlib.h>, लेकिन जोड़ना #importमेरे iOS परीक्षण कार्यक्रम में आवश्यक नहीं था।


11

शायद कुछ की तर्ज पर:

NSUInteger randomIndex = (NSUInteger)floor(random()/RAND_MAX * [theArray count]);

यादृच्छिक संख्या जनरेटर (srandomdev (), उदाहरण के लिए) को प्रारंभ करना न भूलें।

नोट: मैंने नीचे दिए गए उत्तर के अनुसार डॉट सिंटैक्स के बजाय -ाउंट का उपयोग करने के लिए अपडेट किया है।


9
@interface NSArray<ObjectType>  (Random)
- (nullable ObjectType)randomObject;
@end

@implementation NSArray (Random)

- (nullable id)randomObject
{
    id randomObject = [self count] ? self[arc4random_uniform((u_int32_t)[self count])] : nil;
    return randomObject;
}

@end

संपादित करें: Xcode 7. जेनरिक, अशक्तता के लिए अपडेट किया गया


1

एक यादृच्छिक संख्या उत्पन्न करें और इसे सूचकांक के रूप में उपयोग करें। उदाहरण:

#import <Foundation/Foundation.h>

int main(int argc, const char * argv[])
{
    @autoreleasepool {
        NSArray *array = [NSArray arrayWithObjects: @"one", @"two", @"three", @"four", nil];
        NSUInteger randomNumber;
        int fd = open("/dev/random", O_RDONLY);
        if (fd != -1) {
            read(fd, &randomNumber, sizeof(randomNumber));
            close(fd);
        } else {
            fprintf(stderr, "Unable to open /dev/random: %s\n", strerror(errno));
            return -1;
        }
        double scaledRandomNumber = ((double)randomNumber)/NSUIntegerMax * [array count];
        NSUInteger randomIndex = (NSUInteger)floor(scaledRandomNumber);
        NSLog(@"random element: %@", [array objectAtIndex: randomIndex]);
    }
    return 0;
}

@ जोशुआ यदि आप थोड़ा और विस्तार चाहते हैं, तो आप SecRandomCopyBytes()iPhone पर क्रिप्टोग्राफिक रूप से उपयोगी यादृच्छिक संख्या प्राप्त करने के लिए उपयोग कर सकते हैं । मैक पर आप / देव / यादृच्छिक के लिए सीधी पहुँच है।

मुझे लगता है कि सवाल का मुख्य बिंदु यह दिखाना है कि सरणी से यादृच्छिक आइटम कैसे उठाया जाए, और यह उत्तर वास्तव में सर्वोत्तम जानकारी नहीं देता है।
बीकर

मुझे यह मजाक काफी पसंद है, लेकिन मैंने इसे पाने वालों की सहायता के लिए इसे वोट किया।
स्टिग ब्रेउसेट

0
 srand([[NSDate date]  timeIntervalSince1970]);

 int inx =rand()%[array count];

inx यादृच्छिक संख्या है।

जहां रैंडम () रैंडम पिकिंग फंक्शन से पहले प्रोग्राम में कहीं भी हो सकता है।


0
ObjectType *objectVarName = [array objectAtIndex:arc4random_uniform((int)(array.count - 1))];

यदि आप उसे एक इंट में डालना चाहते हैं, तो उस के लिए समाधान (तब उपयोगी है, जब आपको एनम-कॉल की संख्या को यादृच्छिक करने के मामले में गैर-अनुक्रमिक संख्याओं की एक सरणी से यादृच्छिक int की आवश्यकता होती है)

int intVarName = (int)[(NSNumber *)[array objectAtIndex:arc4random_uniform((int)(array.count - 1))] integerValue];

0

स्विफ्ट 4 में:

let array = ["one","two","three","four"]
let randomNumber = arc4random_uniform(UInt32(array.count))

array[Int(randomNumber)]

1
कृपया समीक्षा करें कि मैं एक अच्छा उत्तर कैसे लिखूं । कोड-केवल उत्तर हतोत्साहित किए जाते हैं क्योंकि वे यह नहीं समझाते हैं कि वे प्रश्न में समस्या का समाधान कैसे करते हैं। आपको अपने उत्तर को यह बताने के लिए अपडेट करना चाहिए कि यह क्या करता है और 7 साल पुराने इस प्रश्न के कई उत्तरों पर यह कैसे सुधार करता है
FluffyKitten
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.