Это расширение массива Swift 4 реализует взвешенный случайный выбор, a.k.a Выбор рулетки из ее элементов:
public extension Array where Element == Double {
/// Consider the elements as weight values and return a weighted random selection by index.
/// a.k.a Roulette wheel selection.
func weightedRandomIndex() -> Int {
var selected: Int = 0
var total: Double = self[0]
for i in 1..<self.count { // start at 1
total += self[i]
if( Double.random(in: 0...1) <= (self[i] / total)) { selected = i }
}
return selected
}
}
Например, учитывая массив из двух элементов:
[0.9, 0.1]
weightedRandomIndex()
вернет ноль 90% времени и один 10% времени.
Вот более полный тест:
let weights = [0.1, 0.7, 0.1, 0.1]
var results = [Int:Int]()
let n = 100000
for _ in 0..<n {
let index = weights.weightedRandomIndex()
results[index] = results[index, default:0] + 1
}
for (key,val) in results.sorted(by: { a,b in weights[a.key] < weights[b.key] }) {
print(weights[key], Double(val)/Double(n))
}
выход:
0.1 0.09906
0.1 0.10126
0.1 0.09876
0.7 0.70092
Этот ответ в основном совпадает с ответом Эндрю Мао:
https://stackoverflow.com/a/15582983/74975