0

In Xcode 8 and iOS 10, I used the following code to shuffle values inside an array:

for i in 0..<appSingleton.paxArrayShared.count
{
    let r = Int(arc4random_uniform(UInt32(appSingleton.paxArrayShared.count)))
    // Check if you are not trying to swap an element with itself
    if i != r
    {
        swap(&appSingleton.paxArrayShared[i], &appSingleton.paxArrayShared[r])
    }
}

However, in Xcode 9 and iOS 11, I began receiving the following warning:

Simultaneous accesses to 0x########, but modification requires exclusive access.

enter image description here

Is there a better way to shuffle the array?

Thank you!

Rob
  • 415,655
  • 72
  • 787
  • 1,044
Igor Tupitsyn
  • 1,193
  • 3
  • 18
  • 45
  • 2
    To get around this problem, use `appSingleton.paxArrayShared.swapAt(i, r)`. Re better algorithms (i.e. [Fisher-Yates](https://en.wikipedia.org/wiki/Fisher–Yates_shuffle)) see https://stackoverflow.com/q/24026510/1271826. – Rob Oct 07 '17 at 01:57
  • That's a really poor way to shuffle. Not only can it never guarantee a truly random result, but it takes asymptotically more iterations to even come close. When's the last time you shuffled a deck by swapping 2 pairs of individual cards only 52 times? How awkward was that? – Alexander Oct 07 '17 at 04:05
  • @Alexander - I don't get your comment, "When's the last time you shuffled a deck by swapping 2 pairs of individual cards only 52 times? How awkward was that?" That is effectively what Fisher-Yates does. Sure, it would be an awkward way for a human to shuffle a deck, but it's a very efficient way for a computer to shuffle and avoid biases of techniques like the OP's code. – Rob Oct 07 '17 at 18:18
  • @Rob Fisher Yates essentially builds up a new "random" section of the array, by repeatedly drawing elements from the old "not random" section of the array. As a consequence, no swap during a fisher yates shuffle have the effect of undoing a previous swap, which is exactly what OP's code does – Alexander Oct 08 '17 at 17:33
  • @Alexander - I'm still not understanding your point. Fisher-Yates (FY) does swaps, just like the OPs does. The only difference is that when FY pulls a value out to put it in the new array (which is built in place via the swap), it excludes that value from further swaps, thereby avoiding the significant biases that the OPs code introduces. The problem in the OPs code is not that he's doing a swap, but merely that he's not narrowing down the range of indices that he considers for future swaps. See updated gist: http://gist.github.com/robertmryan/b002b7d524646fd677bb3979c89ec331‌​. – Rob Oct 08 '17 at 19:35
  • 1
    @Rob Yes Rob, that's exactly my point. There's a difference between mindlessly swapping any two random cards a few times (OP's shuffle) vs building up a "shuffled" portion of the array in-place (fisher yates). For one, it guarantees that no swap operation ever undoes the effect of a previous shuffle. The issue isn't the swapping, it's the lack of regard for what's being swapped. – Alexander Oct 09 '17 at 07:51

0 Answers0