I assume that in your example, βprobabilityβ means βweightβ (so people with a probability of 1.0 do not guarantee victory and the total probability will not be 1.0)
You can create a tree of nodes in which leaf nodes contained your individual records:
leaf1 = {:name => "Adam" , :prob => 0.5} leaf2 = {:name => "Ben" , :prob => 1.0}
and each node contained the sum of the nodes below it
node1 = { :prob_sum => 1.5 , :children=> [ leaf1, leaf2] }
The root node then contains the sum of the entire structure
root_node = { :prob_sum => 33 , :children => [ leaf9, leaf10] }
Then you pick a random number between zero and the sum contained in the root of the node.
my_random = rand( root_node.prob_sum )
Then cross the tree. Each node contains the sum of all the nodes below it, so if your random number is greater than node, you subtract the value of node and skip this branch.
def find_node( my_random ): c = children.first() while( c ): if ( c.prob_sum < my_random ): return c.find_node(my_random) my_random -= c.prob_sum c = c.next
Assuming you have built a balanced tree, you should get the results in O (log n)
Alternatively, you can get the same result by adding the current general field to your current dataset and performing a binary search based on this total. This would probably be easier to implement, but only applicable if your working set can fit in memory.
Vorlauf Jan 31 2018-12-12T00 : 00Z
source share