Return random item by its 'weight'/probability

Hi, I have a rather particular conundrum.

I have, for example, these items:

+-----------------+
| fruit  | weight |
+-----------------+
| apple  |   4    |
| orange |   2    |
| lemon  |   1    |
+-----------------+

I need to return a random fruit. But- apple should be picked 4 times more frequently than lemon and 2 times more frequently than orange, and so on.

Does anyone have any ideas as how to smartly do this? It doesn’t need to be done frequently so I don’t mind if it’s not done particularly efficiently.

1 Like

I’d imagine the brute force way is to have one table that has 4 apples in it, 2 oranges, and 1 lemon. Then, you’d choose a random fruit. It’s not sexy, but should work (I think…)

Another idea. Count the total number of pieces (7) and then get a random number between 1 and 7 using random number generator. Then if the number is 1-4 choose apple. If 5-6 choose orange. If 7 choose lemon.

Seems like there’d be a way to make that entirely dynamic.

1 Like

I should have mentioned, that the table of fruits is a dynamic list of Bubble “things”, so while I’d be fine with brute forcing it like this, I don’t know how you could do that in Bubble, as (as far as I’m aware) you can’t have something like a for loop, adding an item a dynamic “x” number of times to a list/table.

This was my initial thought too, but the tricky part is how would I then map the random number back to the initial item (When this is a dynamic list)?

What’s the potential range for each of these…

  • Number of items in the list
  • Weight of each item

They’d be user created items, so there’d be no max values for either. At a guess it’ll probably be lists of around 100 or so, with weights up to 2000.

Okay, so large enough that running a workflow for each potential number is not particularly viable.

One way to do this would be to add an item, say, apples and then add a column for the total count of the weight. For example, the above would get:

  • Apples, Weight = 4, Cumulative Weight = 4
  • Orange, Weight = 2, Cumulative Weight = 6
  • Lemons, Weight = 1, Cumulative Weight = 7

Then, pick a random number between 1 and 7. Let’s say it’s 5 in this instance. Do a search for all items with a cumulative weight greater or equal to 5, sorted lowest to highest, then select the 1st item. In this case Orange.

And, if users are going to delete items, etc. then leave them in the list. Have a column for whether it’s a deleted item. Do cumulative numbers including the deleted items. And, if a deleted item happens to be selected then run the equation again (maybe have to re-write the logic a few times since Bubble doesn’t allow loops).

Think this will work for you?

Yeah, that should work, I’ll give it a try. Thanks :grinning:

1 Like

In case anyone is facing the same issue, I ended up finding a less hands-on solution to the problem.

I found that math.js has a function for returning random items with weighting- function pickRandom (http://mathjs.org/docs/reference/functions/pickRandom.html).

You can populate a query by doing a search for unique IDs and join with “,”. The math.js plugin works if you only have a few entries but failed when I tried with a few hundred, so I had to use the Toolbox plugin and load the math.js script myself. All works fine. Now my only issue is that my application’s resource usage goes through the roof when I output a few hundred things using “join with”.

This topic was automatically closed after 70 days. New replies are no longer allowed.