I have an array exArray
with two types of integer elements: 1
and 2
. I'd like to choose a position $k$ in the array with uniform random probability conditioned on it having an element with the value 1
. Is there a one-liner to do this? Right now I'm using RandomInteger[{1,arrayLength}]
, which is a ridiculous way to proceed.
2 Answers
RandomChoice[Flatten[Position[{1, 2, 2, 2, 1, 1, 2, 2, 1, 2, 2, 2, 1}, 1]]]
Sjoerd already gave one good option, but depending on the circumstance a proceedural trial-and-error approach may be superior. If you want to generate a many random positions from a given list it would be better to find all "ones" positions and then use RandomSample
and/or RandomChoice
to extract what you want. However if you only want a limited number of random positions from a particular list it will be much faster to merely generate a random position, extract that element and check it, and start over if it is not the target type. Here is an example:
n = 5000000;
a = RandomInteger[{1, 2}, n];
RandomChoice[Join @@ Position[a, 1]] // Timing
{0.983, 4227176}
So it takes almost a second (on my machine) to pick a random "one" from the five million element list a
. However we can generate 50,000 random "ones" positions in a fraction of the time with trial-and-error:
Table[
For[p = 0, a[[p]] =!= 1, p = RandomInteger[{1, n}]]; p,
{50000}
] // Timing // First
0.156
So a single random position takes about 3.12*10^-6 seconds. This assumes a uniform distribution of ones and non-ones, and a smaller percent of "target" values will result in longer average times, but I hope this illustrates the potential performance of this method.