I'm trying to create a function that randomly returns a value from a list but remembers the values that have been given before. At the end when the list is empty it should return an empty list. Basically like emptying a bucket full of eggs one at a time.

Suppose I have two lists:

data1 = Range[10];
data2 = Range[20];

Assume a function

getRandomItem[l_List]

I tried playing with down-values but that doesn't work.

Calling getRandomItem[data1] two times would give (e.g) {1} and {3}. Calling getRandomItem[data2] two times would give (e.g) {15} and {20}

At the end as stated before when all items are chosen both
getRandomItem[data1] and getRandomItem[data2]
should return {}.

I would like to do that without declaring data1 and data2 as global variables nor do I which to change/alter them.
So, basically I presume the function itself should remember which data has been given to it and where it had left the previous time.

Yes I realize that but using global variables is also a bit cumbersome (could add a counter field in the list e.g). So I just wondered if there's a neat way to do this. Perhaps there isn't..
–
LouApr 11 '12 at 14:15

Yes I noticed that :) Using getRandomItem[{1,2,3}] as a downvalue didn't work either since it's up in the downvalue pattern matching stack.
–
LouApr 11 '12 at 14:19

3

Have you looked at RandomSample? if the critical component is sampling without replacement, that is a good place to start.
–
Andy RossApr 11 '12 at 14:21

What you describe reminds me a bit of closures (which I haven't used much personally). Please see if my answer is helpful.
–
SzabolcsApr 11 '12 at 14:26

I did but it doesn't seem to solve anything. RandomChoice is perfect already. I wanted to push the housekeeping to the function but it seemed complicated and perhaps to be avoided. Calling the function with any list until it's empty is essentialy the goal.
–
LouApr 11 '12 at 14:30

only outputs the random number, and can be re-evaluated until it's used them all up, and it outputs {}. This is actually faster than the previous version (same benchmark runs in 0.7657132) and has a simpler usage.

Here's a more imperative solution, still based on closing over a mutable symbol, if for some reason you don't want to pre-randomize the list. I'm not sure I'd recommend it, but it's an alternative approach that might be interesting:

Its speed is comparable to Eli Lansey's approach for a 100000 element list if you're going to drip away the whole bucket; the advantage comes about if you're only using a small number of drips, because you only have to pay for the ones you use. Still, for most applications I'd just use RandomSample.

Mathematica is a registered trademark of Wolfram Research, Inc. While the mark is used herein with the limited permission of Wolfram Research, Stack Exchange and this site disclaim all affiliation therewith.