Swift: Shuffle Array of Any Type

Swift makes easy work of shuffling the contents of any type of array. In the example that follows I based my shuffle algorithm on Fisher–Yates shuffle (aka as Donald Knuth shuffle).

The pseudo code for the shuffle looks as follows:

for i from n − 1 downto 1 do
j ← random integer with 0 ≤ j ≤ i
exchange a[j] and a[i]

This algorithm does an excellent job of randomizing the results (see below for sample output).

I mapped the above pseudo code to Swift as follows:

1
2
3
4
5
6
7
8
9
10
11
12
13
func shuffleArray<T>(array: Array<T>) -> Array<T>
{
  for var index = array.count - 1; index > 0; index--
  {
    // Random int from 0 to index-1
    var j = Int(arc4random_uniform(UInt32(index-1)))
 
    // Swap two array elements
    // Notice '&' required as swap uses 'inout' parameters
    swap(&array[index], &array[j])
  }
  return array
}

The shuffle is a generic function that accepts an array of any type (T) and returns the same type.

The code is very short, primarily given that Swift includes a global swap function to exchange to elements in the array to be shuffled. You can read more about swapping two array elements, inout parameters and generic functions on this post Swap Array Values and Understanding In-Out Parameters

Shuffle Array of Strings

Let’s start by shuffling an array of strings:

var arrStr = ["hops", "water", "yeast", "grains"]
println("strings: \(shuffleArray(arrStr))")
println("strings: \(shuffleArray(arrStr))")
println("strings: \(shuffleArray(arrStr))")

The output follows, notice that each shuffle returns a different order:

strings: [grains, yeast, hops, water]
strings: [water, hops, grains, yeast]
strings: [yeast, grains, water, hops]

Shuffle Array of Integers/Doubles

The beauty of the generic function is that we can send in any data type, let’s try an array of numbers (doubles in this case):

var arrNum = [5.7, 99.99, 123.123, 0.1_01]
println("nums: \(shuffleArray(arrNum))")
println("nums: \(shuffleArray(arrNum))")
println("nums: \(shuffleArray(arrNum))")

nums: [99.99, 123.123, 0.101, 5.7]
nums: [5.7, 0.101, 99.99, 123.123]
nums: [123.123, 99.99, 5.7, 0.101]

Shuffle Array of Objects (NSArray)

The shuffle also works on an NSArray, which has a collection of objects (versus string, doubles, etc). Swift uses type inference to determine the type of the array, in this case NSArray, as I’ve included several different types in the array (string, int and arrays).

Look carefully at line 1 below, I’ve included the string array (arrStr) and the array of doubles (arrNum) in the array definition:

1
2
3
var arrMixed = ["beer", arrNums, 999, arrStr]
println("mixed: \(shuffleArray(arrMixed))")
println("mixed: \(shuffleArray(arrMixed))")

The output for the shuffled NSArray:

mixed: [(
“123.123”,
“99.98999999999999”,
“5.7”,
“0.101”
), 999, (
yeast,
grains,
water,
hops
), beer]

mixed: [(
yeast,
grains,
water,
hops
), 999, beer, (
“123.123”,
“99.98999999999999”,
“5.7”,
“0.101”
)]