2009-04-26 7 views
38

में एनएसएआरएआर को यादृच्छिक बनाने के लिए कैननिकल तरीका उद्देश्य सी में किसी सरणी को यादृच्छिक बनाने का एक कैननिक तरीका है?उद्देश्य सी

+1

संभव डुप्लिकेट [क्या एक NSMutableArray शफ़ल करने के लिए सबसे अच्छा तरीका है?] (Http: // stackoverflow .com/प्रश्न/56648/whats-the-best-way-to-shuffle-an-nsmutablearray) – Senseful

+1

अनुशंसा [फिशर-येट्स] है (https://en.wikipedia.org/wiki/Fisher%E2%80% 93Yates_shuffle) NSMutableArray के लिए: 'के लिए (NSUInteger i = self.count; i> 1; i--) [self exchangeObjectAtIndex: i - 1 के साथ ऑब्जेक्टएट इंडेक्स: arc4random_uniform ((u_int32_t) i)]; ' –

उत्तर

59

मेरे उपयोगिता पुस्तकालय यह करने के लिए NSMutableArray पर इस श्रेणी को परिभाषित करता है:

@interface NSMutableArray (ArchUtils_Shuffle) 
- (void)shuffle; 
@end 

// Chooses a random integer below n without bias. 
// Computes m, a power of two slightly above n, and takes random() modulo m, 
// then throws away the random number if it's between n and m. 
// (More naive techniques, like taking random() modulo n, introduce a bias 
// towards smaller numbers in the range.) 
static NSUInteger random_below(NSUInteger n) { 
    NSUInteger m = 1; 

    // Compute smallest power of two greater than n. 
    // There's probably a faster solution than this loop, but bit-twiddling 
    // isn't my specialty. 
    do { 
     m <<= 1; 
    } while(m < n); 

    NSUInteger ret; 

    do { 
     ret = random() % m; 
    } while(ret >= n); 

    return ret; 
} 

@implementation NSMutableArray (ArchUtils_Shuffle) 

- (void)shuffle { 
    // http://en.wikipedia.org/wiki/Knuth_shuffle 

    for(NSUInteger i = [self count]; i > 1; i--) { 
     NSUInteger j = random_below(i); 
     [self exchangeObjectAtIndex:i-1 withObjectAtIndex:j]; 
    } 
} 

@end 

सुनिश्चित करें कि आप यादृच्छिक संख्या जनरेटर कुछ समय से पहले आप इसे कहते हैं (उदा srandom(time(NULL)) के साथ) बीज करते हैं; अन्यथा आउटपुट बहुत यादृच्छिक नहीं होगा।

+0

इसे प्यार करो! साझा करने के लिए धन्यवाद। मैं अब आपकी बाकी उपयोगिता पुस्तकालय के बारे में बेहद उत्सुक हूं। – PEZ

+0

इसमें से अधिकांश एल्गोरिदमिक नहीं है - यह सब कुछ है [NSArray arrayWithCount: संख्या:] (जहां "संख्याएं" युगल हैं) - [UIView moveToSuperview: withFrame: एनिमेटेड:], साथ ही किक्स के लिए एकल-ऑब्जेक्ट कोर डेटा स्टैक । –

+0

यह मेरे लिए काम नहीं करता है। मेरा मतलब है कि यह "थोड़ा" shuffles लेकिन कुछ हिस्सों अभी भी क्रम में हैं। उसी सरणी को भी दिया गया पहला शफल हमेशा एक ही परिणाम होता है। इसलिए यह वास्तव में यादृच्छिक नहीं है। –

2

यदि आप यही पूछ रहे हैं तो एसडीके में कोई भी नहीं बनाया गया है।

आप किसी भी यादृच्छिकता या शफलिंग एल्गोरिदम का उपयोग कर सकते हैं, हालांकि आप चाहते हैं। विभिन्न एल्गोरिदम

http://en.wikipedia.org/wiki/Shuffling#Shuffling_algorithms

एल्गोरिदम कि शफ़ल "यथा-स्थान" के लिए एक परिवर्तनशील सरणी के साथ शुरू का उपयोग

insertObject:atIndex: 
removeObjectAtIndex: 

एल्गोरिदम कि फिर से संगठित के लिए, अनियमितता, दक्षता के मामले में अलग-अलग समझौते होते हैं आदि सरणी, इसे मूल फ़ीड और एक नई सरणी बनाएँ।

7
if ([array count] > 1) { 
    for (NSUInteger shuffleIndex = [array count] - 1; shuffleIndex > 0; shuffleIndex--) 
     [array exchangeObjectAtIndex:shuffleIndex withObjectAtIndex:random() % (shuffleIndex + 1)]; 
} 

यादृच्छिक() फ़ंक्शन को srandomdev() या srandom() के साथ बीज बनाना सुनिश्चित करें।

+0

जो आपने लिखा है वह एक उदाहरण विधि के रूप में समझ में नहीं आता है। चूंकि कोड मौजूद है, यह केवल एक समारोह या वर्ग विधि होना चाहिए। Idiomatically, यह एक एनएसएआरएआरई उदाहरण विधि होनी चाहिए जो एक नया, शफल सरणी या एक एनएसएमयूटेबलएरे उदाहरण विधि देता है जो खुद को शफल करता है। – Chuck

+0

सच है, मैं बस यहां कोड का प्रदर्शन कर रहा था, वास्तव में इसे एक श्रेणी में रखने के बारे में चिंतित नहीं था। मैं srandomdev() या srandom() के साथ यादृच्छिक() फ़ंक्शन को बीज का उल्लेख करना भी भूल गया। –

+2

मॉड्यूल के कारण यह कोड थोड़ा पक्षपातपूर्ण है; इस बारे में अधिक जानने के लिए http://en.wikipedia.org/wiki/Fisher-Yates_shuffle#Modulo_bias देखें। –

0

वहाँ NSArray पर एक वर्ग बनाने के बिना एक विहित रास्ता (अर्थात arrayWithRandomizedIndices की तरह एक उदाहरण विधि है) या NSMutableArray (अर्थात randomizeIndices की तरह एक विधि है) नहीं है।

यहां मेरी लाइब्रेरी का एक उदाहरण है, NSMutableArray पर एक श्रेणी का हिस्सा। यह कुछ प्रविष्टियों को घुमाने के बजाय, सरणी को यादृच्छिक रूप से पुन: व्यवस्थित करेगा।

- (void) randomizeIndices 
{ 
    if (self == nil || [self count] <= 1) 
    { 
    return; 
    } 

    int count = [self count]; 

    NSMutableArray* copySelf = [NSMutableArray arrayWithArray:self]; 
    NSMutableArray* mutableResultArray = [NSMutableArray alloc]; 
    mutableResultArray = [mutableResultArray initWithCapacity:count]; 
    [mutableResultArray autorelease]; 

    int objectsMovedCount = 0; 

    for (int i = 0; i < count; i++) 
    { 
    int index = rand() % (count - objectsMovedCount); 
    id anObject = [copySelf objectAtIndex:index]; 
    [mutableResultArray addObject:anObject]; 
    [copySelf removeObjectAtIndex:index]; 
    objectsMovedCount++; 
    } 
    [self setArray:mutableResultArray]; 
} 

कॉल srand(time(0)); या इस विधि या विधि के शुरू में कॉल करने से पहले कुछ इस तरह।

1

मेरा समाधान एक श्रेणी विधि है जो सरणीकृत तत्वों (autoreleased) की प्रतिलिपि बनाते हैं (arc4random का उपयोग करके)।

@interface NSArray (CMRandomised) 

/* Returns a copy of the array with elements re-ordered randomly */ 
- (NSArray *)randomised; 

@end 

/* Returns a random integer number between low and high inclusive */ 
static inline int randomInt(int low, int high) 
{ 
    return (arc4random() % (high-low+1)) + low; 
} 

@implementation NSArray (CMRandomised) 

- (NSArray *)randomised 
{ 
    NSMutableArray *randomised = [NSMutableArray arrayWithCapacity:[self count]]; 

    for (id object in self) { 
     NSUInteger index = randomInt(0, [randomised count]); 
     [randomised insertObject:object atIndex:index]; 
    } 
    return randomised; 
} 

@end 
20

यहां यह है!

- (NSArray*)shuffleArray:(NSArray*)array { 

    NSMutableArray *temp = [[NSMutableArray alloc] initWithArray:array]; 

    for(NSUInteger i = [array count]; i > 1; i--) { 
     NSUInteger j = arc4random_uniform(i); 
     [temp exchangeObjectAtIndex:i-1 withObjectAtIndex:j]; 
    } 

    return [NSArray arrayWithArray:temp]; 
} 
0
ऑब्जेक्टिव-सी श्रेणी विधि के रूप में

NSArray यादृच्छिकीकरण:

@implementation NSArray (NGDataDynamics) 

- (NSArray *)jumbled 
{ 
    NSMutableArray *jumbled = self.mutableCopy; 

    NSUInteger idx = self.count-1; 
    while(idx) 
    { 
    [jumbled exchangeObjectAtIndex:idx 
       withObjectAtIndex:arc4random_uniform(idx)]; 
    idx--; 
    } 

    return jumbled; 
} 

@end 

के रूप में देखी गई: NSArray Randomization & Psychedelia

की