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.
Answer
How about making a closure? A closure is a function with an internal state.
makeDrippingBucket[list_] :=
Module[{bucket = list},
If[bucket === {}, {},
With[{item = RandomChoice[bucket]},
bucket = DeleteCases[bucket, item]; {item}]] &]
Then use this to make a "bucket", like this:
bucket = makeDrippingBucket[{1,2,3,4,5}]
This object has an internal state that changes every time you call it. Every time you call bucket[]
, it will give you a new number, until it gets empty.
bucket[]
(* ==> {3} *)
EDIT
The same thing, using @Eli's solution of pre-randomizing the list:
makeDrippingBucket[list_] :=
Module[{bucket = RandomSample[list]},
If[bucket === {}, {},
With[{item = Last[bucket]}, bucket = Most[bucket]; {item}]] &]
Comments
Post a Comment