1
$\begingroup$

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.

$\endgroup$
1
$\begingroup$
RandomChoice[Flatten[Position[{1, 2, 2, 2, 1, 1, 2, 2, 1, 2, 2, 2, 1}, 1]]]
$\endgroup$
0
$\begingroup$

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.

$\endgroup$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.