What's the Best Way to Shuffle an NSMutableArray?

后端 未结 12 1719
太阳男子
太阳男子 2020-11-21 11:53

If you have an NSMutableArray, how do you shuffle the elements randomly?

(I have my own answer for this, which is posted below, but I\'m new to Cocoa an

12条回答
  •  眼角桃花
    2020-11-21 12:28

    If elements have repeats.

    e.g. array: A A A B B or B B A A A

    only solution is: A B A B A

    sequenceSelected is an NSMutableArray which stores elements of class obj, which are pointers to some sequence.

    - (void)shuffleSequenceSelected {
        [sequenceSelected shuffle];
        [self shuffleSequenceSelectedLoop];
    }
    
    - (void)shuffleSequenceSelectedLoop {
        NSUInteger count = sequenceSelected.count;
        for (NSUInteger i = 1; i < count-1; i++) {
            // Select a random element between i and end of array to swap with.
            NSInteger nElements = count - i;
            NSInteger n;
            if (i < count-2) { // i is between second  and second last element
                obj *A = [sequenceSelected objectAtIndex:i-1];
                obj *B = [sequenceSelected objectAtIndex:i];
                if (A == B) { // shuffle if current & previous same
                    do {
                        n = arc4random_uniform(nElements) + i;
                        B = [sequenceSelected objectAtIndex:n];
                    } while (A == B);
                    [sequenceSelected exchangeObjectAtIndex:i withObjectAtIndex:n];
                }
            } else if (i == count-2) { // second last value to be shuffled with last value
                obj *A = [sequenceSelected objectAtIndex:i-1];// previous value
                obj *B = [sequenceSelected objectAtIndex:i]; // second last value
                obj *C = [sequenceSelected lastObject]; // last value
                if (A == B && B == C) {
                    //reshufle
                    sequenceSelected = [[[sequenceSelected reverseObjectEnumerator] allObjects] mutableCopy];
                    [self shuffleSequenceSelectedLoop];
                    return;
                }
                if (A == B) {
                    if (B != C) {
                        [sequenceSelected exchangeObjectAtIndex:i withObjectAtIndex:count-1];
                    } else {
                        // reshuffle
                        sequenceSelected = [[[sequenceSelected reverseObjectEnumerator] allObjects] mutableCopy];
                        [self shuffleSequenceSelectedLoop];
                        return;
                    }
                }
            }
        }
    }
    

提交回复
热议问题