I know there is a new shuffle method with iOS 9 but I am wondering if there is anyway to shuffle two arrays the same way?
For example
[1,2,3,4] and [a,b,c,d]
shuffle
[3,4,1,2] and [c,d,a,b]
I know there is a new shuffle method with iOS 9 but I am wondering if there is anyway to shuffle two arrays the same way?
For example
[1,2,3,4] and [a,b,c,d]
shuffle
[3,4,1,2] and [c,d,a,b]
Using the shuffle()
method from How do I shuffle an array in Swift? and the ideas from How can I sort multiple arrays based on the sorted order of another array
you can shuffle the array indices and then re-order both (or more)
arrays accordingly:
let a = [1, 2, 3, 4]
let b = ["a", "b", "c", "d"]
var shuffled_indices = a.indices.shuffle()
let shuffled_a = Array(PermutationGenerator(elements: a, indices: shuffled_indices))
let shuffled_b = Array(PermutationGenerator(elements: b, indices: shuffled_indices))
print(shuffled_a) // [3, 1, 2, 4]
print(shuffled_b) // ["c", "a", "b", "d"]
Update for Swift 3 (Xcode 8): PermutationGenerator
does not
exist in Swift 3 anymore.
Using the shuffled()
method
from Shuffle array swift 3 the same can be achieved with
var shuffled_indices = a.indices.shuffled()
let shuffled_a = shuffled_indices.map { a[$0] }
let shuffled_b = shuffled_indices.map { b[$0] }
Use a dictionary to store the values temporarily, shuffle the keys and then rebuild the other array by extracting the values from the dictionary.
I'm unaware of any built-in shuffle mechanism in Swift 2.0. Assuming this doesn't exist, I borrowed some code from here.
extension CollectionType where Index == Int {
/// Return a copy of `self` with its elements shuffled
func shuffle() -> [Generator.Element] {
var list = Array(self)
list.shuffleInPlace()
return list
}
}
extension MutableCollectionType where Index == Int {
/// Shuffle the elements of `self` in-place.
mutating func shuffleInPlace() {
// empty and single-element collections don't shuffle
if count < 2 { return }
for i in 0..<count - 1 {
let j = Int(arc4random_uniform(UInt32(count - i))) + i
guard i != j else { continue }
swap(&self[i], &self[j])
}
}
}
let shuffleOrder = [0,1,2,3]
let shuffled = shuffleOrder.shuffle()
var newArray1 = [String]()
var newArray2 = [String]()
let array1 = ["a", "b", "c", "d"]
let array2 = ["w", "x", "y", "z"]
shuffled.forEach() { index in
newArray1.append(array1[index])
newArray2.append(array2[index])
}
This solves the problem in a really straight forward way. It creates an array, shuffleOrder
, that just has an index for each possible index in the starting arrays. It then shuffles these indices to create a random sampling order. Finally, it constructs two new arrays, based off of the starting arrays, sampling them with the shuffled
values. While this doesn't mutate the original 2 arrays in place, it would be simple to modify this to do so.
Based upon Martin R's original answer, you could approach the problem using GameKit.
The answer is written in Swift4:
var arrayA = [1, 2, 3, 4]
var arrayB = ["a", "b", "c", "d"]
//Get The Indices Of The 1st Array
var shuffledIndices: [Int] = Array(arrayA.indices)
print("Shuffled Indices = \(shuffledIndices)")
//Shuffle These Using GameKit
shuffledIndices = GKRandomSource.sharedRandom().arrayByShufflingObjects(in: shuffledIndices) as! [Int]
//Map The Objects To The Shuffled Indices
arrayA = shuffledIndices.map { arrayA[$0] }
arrayB = shuffledIndices.map { arrayB[$0] }
//Log The Results
print("""
Array A = \(arrayA)
Array B = \(arrayB)
""")
Hope it helps ^_________^.