Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    primarykey
    data
    text
    <p>What are you describing is called <strong>rejection sampling</strong>, and is a bad idea. For example if you wanted only numbers <code>&gt;0.999</code>, it would take <strong>1000 times longer</strong> to generate them.</p> <hr> <p><strong>Best way</strong></p> <p>The correct way to do this is to use another sampling technique, such as using the inverse of the CDF (cumulative density function), and doing <code>[inverseCDF(random()) for _ in range(10)]</code>. In your case, this would be, like GaretJax suggests, <code>[0.5+random()/2 for _ in range(10)]</code></p> <hr> <p><strong>Intent</strong></p> <p>I think your intent was being able to further filter based on the entire expression of a list comprehension. In that case, you would put your iterable (here with parentheses rathern than [...] for laziness, though it doesn't matter) inside another comprehension:</p> <pre><code>[r for r in (random.random() for x in range(10)) if r&gt;0.5] </code></pre> <p>For a better solution along these lines that can handle rejection, see the "Solution with list comprehensions only" section or <a href="https://stackoverflow.com/a/6894840/711085">eryksun's answer</a>.</p> <hr> <p><strong>Solution with generators</strong></p> <p>(see below for a list-comprehension only solution)</p> <p>You can do this for any linear range. If your rejection function is arbitrarily complex however, a general way to do rejection sampling would be as follows. (Again, a very bad idea unless you know what you're doing and efficiency doesn't matter.)</p> <pre><code>from random import random from itertools import * def randoms(): while True: yield random() def rejectionSample(pred, n): return islice(filter(pred, randoms()), n) </code></pre> <p>Example:</p> <pre><code>&gt;&gt;&gt; print( list(rejectionSample(lambda x:x&gt;0.5)) ) [0.6656564857979361, 0.9850389778418555, 0.9607471536139308, 0.9191328900300356, 0.810783093197139] </code></pre> <p>You could also do something like:</p> <pre><code>def rejectionSample(pred, n): count = 0 while count&lt;n: r = random() if pred(r): yield r count += 1 </code></pre> <hr> <p><strong>Solution with list comprehensions only</strong></p> <p>However since you want to use list comprehensions <em>only</em>, this means <strong>the expression-part of your comprehension cannot fail</strong>, so you have to somehow embed a while loop in the comprehension. This is impossible to do with a single lambda function alone, but we can pull it off as long as we have some recursive/loopy primitive, for example...</p> <pre><code>[next(filter(pred,randoms())) for _ in range(10)] </code></pre> <p>(If you really wanted a one-liner list comprehension, <code>randoms()</code> can be rewritten as <code>(random() for _ in count())</code>.) Again, this is unnecessary if you easily find the analytic inverse cumulative distribution function for your particular distribution.</p> <hr> <p><strong>edit</strong>: I take that back... it... <strong>is possible</strong>... with just lambdas...</p> <p><strong>DEAR GOD HAVE MERCY WHAT HORRORS HAVE I UNLEASHED UPON THE WORLD NOOOOOO</strong></p> <pre><code>[ (lambda f:f(f,random()))(lambda self,r:r if r&gt;0.5 else self(self,random())) for _ in range(10) ] </code></pre>
    singulars
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. VO
      singulars
      1. This table or related slice is empty.
    2. VO
      singulars
      1. This table or related slice is empty.
    3. VO
      singulars
      1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload