* Returns a weighted random element from the given array. Each element of the array should be an object with two keys `weight` and `value`. * * - Each `weight` key should be a number representing the probability of selecting the value, relative to the sum of the weights. Weights can be any pos
(
array: ReadonlyArray<{
/**
* The weight of the value.
*/
weight: number;
/**
* The value to pick.
*/
value: T;
}>
)
| 968 | * @since 8.0.0 |
| 969 | */ |
| 970 | weightedArrayElement<const T>( |
| 971 | array: ReadonlyArray<{ |
| 972 | /** |
| 973 | * The weight of the value. |
| 974 | */ |
| 975 | weight: number; |
| 976 | /** |
| 977 | * The value to pick. |
| 978 | */ |
| 979 | value: T; |
| 980 | }> |
| 981 | ): T { |
| 982 | if (array.length === 0) { |
| 983 | throw new FakerError( |
| 984 | 'weightedArrayElement expects an array with at least one element' |
| 985 | ); |
| 986 | } |
| 987 | |
| 988 | if (!array.every((elt) => elt.weight > 0)) { |
| 989 | throw new FakerError( |
| 990 | 'weightedArrayElement expects an array of { weight, value } objects where weight is a positive number' |
| 991 | ); |
| 992 | } |
| 993 | |
| 994 | const total = array.reduce((sum, { weight }) => sum + weight, 0); |
| 995 | const random = this.faker.number.float({ |
| 996 | min: 0, |
| 997 | max: total, |
| 998 | }); |
| 999 | let current = 0; |
| 1000 | for (const { weight, value } of array) { |
| 1001 | current += weight; |
| 1002 | if (random < current) { |
| 1003 | return value; |
| 1004 | } |
| 1005 | } |
| 1006 | |
| 1007 | // In case of rounding errors, return the last element |
| 1008 | // eslint-disable-next-line @typescript-eslint/no-non-null-assertion |
| 1009 | return array.at(-1)!.value; |
| 1010 | } |
| 1011 | |
| 1012 | /** |
| 1013 | * Returns a subset with random elements of the given array in random order. |
no test coverage detected