Reputation: 89
I have the following problem:
I need to choose a random object from an List
. This is simple, if all elements would have the same chance to be picked.
In my case, the chance of an object being picked is stored in another List
. So I need a method, that randomly picks an element from the list based on the other List
.
EDIT: E.g.
List<String> objects = Arrays.asList("one","two","three");
List<Double> chance = Arrays.asList(0.25, 0.25, 0.5);
Now I want the String
"one
" and "two
" with a chance of one out of four and the String
"three
" with a chance of one out of two.
Thank you for any advice.
Upvotes: 0
Views: 2088
Reputation: 45005
You could a TreeMap
with as key the current total of the previous probabilities and as value the corresponding object, then generate a random number between 0
and 1
, and finally use ceilingEntry(K key)
to get the object corresponding to the first key that is greater or equal to the current random value.
Something like:
List<String> objects = Arrays.asList("one","two","three");
List<Double> chance = Arrays.asList(0.25, 0.25, 0.5);
// Build the tree map
TreeMap<Double, String> map = new TreeMap<>();
double total = 0.0d;
for (int i = 0; i < objects.size(); i++) {
map.put(total += chance.get(i), objects.get(i));
}
System.out.printf("The generated is map %s%n", map);
// The generator of random numbers
Random generator = new Random();
// Generate a random value between 0 and 1
double value = generator.nextDouble();
// Get the object that matches with the generated number
String object = map.ceilingEntry(value).getValue();
System.out.printf("The current value is %f corresponding to '%s'%n", value, object);
Output:
The generated map is {0.25=one, 0.5=two, 1.0=three}
The current value is 0,048460 corresponding to 'one'
So here:
0.25
, we will get "one
".0.25
(excluded) and 0.50
(included), we will get "two
".0.50
(excluded) and 1.0
(included), we will get "three
".Thanks to the fact that nextDouble()
returns a double
value uniformly distributed between 0.0
and 1.0
, this is good enough to get the expected distribution.
Upvotes: 3