scriptName "Functions\arrays\fn_selectRandomWeighted.sqf"; /* File: fn_selectRandomWeighted.sqf Author: Joris-Jan van 't Land Description: Function to select a random item from an array, taking into account item weights. The weights should be Numbers between 0 and 1, with a maximum precision of hundreds. Parameter(s): _this select 0: source Array (Array of Any Value) _this select 1: weights (Array of Number) Returns: Any Value selected item TODO: [*] Algorithm is inefficient? */ private ["_array","_weights","_index","_weighted"]; _array = _this select 0; _weights = _this select 1; //Parameter validation. if ((typeName _array) != (typeName [])) exitWith {debugLog "Log: [selectRandomWeighted] Array (0) must be an Array!"; nil}; if ((typeName _weights) != (typeName [])) exitWith {debugLog "Log: [selectRandomWeighted] Weights (1) must be an Array!"; nil}; if ((count _array) > (count _weights)) exitWith {debugLog "Log: [selectRandomWeighted] There must be at least as many elements in Weights (1) as there are in Array (0)!"; nil}; //Created weighted array of indices. private ["_weighted"]; _weighted = []; for "_i" from 0 to ((count _weights) - 1) do { private ["_weight"]; _weight = _weights select _i; //Ensure the weight is a Number. //If it's not, set weight to 0 to exclude it. if ((typeName _weight) != (typeName 0)) then {debugLog "Log: [selectRandomWeighted] Weights should be Numbers; weight set to 0!"; _weight = 0}; //The weight should be a Number between 0 and 1. if (_weight < 0) then {debugLog "Log: [selectRandomWeighted] Weights should be more than or equal to 0; weight set to 0!"; _weight = 0}; //if (_weight > 1) then {debugLog "Log: [selectRandomWeighted] Weights should be less than or equal to 1; weight set to 1!"; _weight = 1}; //Normalize the weight for a precision of hundreds. _weight = round(_weight * 100); for "_k" from 0 to (_weight - 1) do { _weighted = _weighted + [_i]; }; }; //Randomly select an index from the weighted array and therefore an element. private ["_index"]; _index = _weighted call BIS_fnc_selectRandom; _array select _index