0

I have a function which returns a string of size N containing a random sequence of characters form a small set {A,B,C,D}. I generate this line as:

def gen_line(N):
  tline = ""
  for i in range(N):
    xrand = random.random()
    if( xrand < 0.25 ):
      ch = "A" 
    elif( xrand < 0.50 ):
      ch = "B" 
    elif( xrand < 0.75 ):
      ch = "C" 
    elif( xrand < 1.00 ):
      ch = "D" 
    else:
      print "ERROR: xrand = %f"%( xrand )
    tline = tline+ch
  return tline

but this is, no doubt, a very inefficient way to do things. Is there a better, more pythonic, way to accomplish this?

drjrm3
  • 4,474
  • 10
  • 53
  • 91

2 Answers2

2

Try using random.choice with str.join.

>>> x = 'abcd'
>>> ''.join(random.choice(x) for _ in range(10))
'aabbdbadbc'
Shashank
  • 13,713
  • 5
  • 37
  • 63
  • 1
    @ndpu The problem with random.sample is that it samples without replacement. You will not be able to generate strings like 'aa'. – Shashank May 06 '15 at 18:57
  • This is actually much slower. Why would that be? I am looking for a line of length 60, if it matters. It takes maybe twice as long. – drjrm3 May 06 '15 at 19:10
  • 1
    @Laurbert515 There are several reasons why it could be slower, so I'm not sure. Benchmarks are often difficult to explain without rigorous testing and source code analysis. Instead of using `random.choice`, you could try `n = len(x) - 1; ''.join(x[randint(0, n)] for _ in xrange(N))` Who knows, it could be faster or slower than other methods. Or just use np.random.choice from the other answer. – Shashank May 06 '15 at 19:29
0

You can use np.random.choice:

In [13]:

import random
a = np.array(list('abcd'))
%timeit ''.join(np.random.choice(a, 10000))
​
def gen_line(N):
  tline = ""
  for i in range(N):
    xrand = random.random()
    if( xrand < 0.25 ):
      ch = "A" 
    elif( xrand < 0.50 ):
      ch = "B" 
    elif( xrand < 0.75 ):
      ch = "C" 
    elif( xrand < 1.00 ):
      ch = "D" 
    else:
      print("ERROR: xrand = %f"%( xrand ))
    tline = tline+ch
  return tline
​
%timeit gen_line(10000)
100 loops, best of 3: 6.39 ms per loop
100 loops, best of 3: 11.7 ms per loop
EdChum
  • 376,765
  • 198
  • 813
  • 562