3

I'm trying to generate a random string using the elements of a different string, with the same length.

Ex) String: AGAACGC

I want a random string using only elements from the string above

Right now I have:

import random
seq = 'AGAACGC'
length = len(seq)    

for blah in range(len(seq)): #Apologies for the lame variable names
    x = random.randint(0,length - 1)
    print seq[x]

And of course this will give me something like:

A

A

G

A

C

A

A

How would I alter the program so that it prints out my random string on one line?

I'm hoping for a relatively simple answer, as I'm still a beginner in python, so I don't want to get too fancy. But any help at all would be appreciated.

And is there a way to repeat the randomization 'n' number of times?

Say instead of 1 random string, I wanted 4 random strings on different lines. Is there an easy way doing this? (My newbish mind is telling me to repeat the loop 'n' times...but it needs to be a changeable number of randomized strings)

Sorry for asking. I'd really appreciate some help. I'm stuck on a bigger problem because I don't know how to do these steps.

3
  • Do you want it on one line with spaces in between, or without?
    – abarnert
    Commented Apr 29, 2015 at 0:26
  • Without spaces please! Thanks
    – Memo Smith
    Commented Apr 29, 2015 at 0:29
  • 1
    As a side note, when Python forces you to give a name to something that you don't care about, instead of naming it blah, the usual convention is to name it _. (Unless you're using gettext or similar i18n, which gives a special meaning for _, in which case your project probably has its own convention—maybe __ or dummy—that you should follow.)
    – abarnert
    Commented Apr 29, 2015 at 0:35

2 Answers 2

2

In Python 3, there is a simple way to print a character without a newline, but in Python 2, there isn't.* So, the simplest way to do this is to build up the string, then print it at the end:

result = ''
for blah in range(len(seq)): #Apologies for the lame variable names
    x = random.randint(0,length - 1)
    result += seq[x]
print result

* There are two less simple ways: You can use from __future__ import print_function and then use Python 3 print syntax instead of Python 2, or you can use sys.stdout.write(seq[x]) for each character and then sys.stdout.write('\n') and sys.stdout.flush() at the end. But I don't think you want either of those.


However, there are a number of ways to improve this:

  • Use randrange(length) instead of randint(0, length - 1).
  • Use random.choice(seq) instead of using randrange or randint in the first place.
  • Use _ instead of blah for "don't care" variables.*
  • If you don't care about what you're iterating over, just that you're iterating once for each character, just do for _ in seq:, not for _ in range(len(seq)):.
  • Build up a list of letters, then call ''.join() at the end, instead of building up a string.
  • Use a comprehension instead of an explicit loop.

Putting that all together:

print ''.join(random.choice(seq) for _ in seq)

* Unless you're using gettext for i18n, or something else that gives _ a special meaning. Most projects that do that come up with their own convention for "don't care" names—maybe __, or dummy. And of course blah would be fine for such a project, as long as you used it consistently.


As for repeating it, your newbish mind is right; just use a loop. For example (taking the second version, but it'll work just as well with the first):

n = 4
for _ in range(n):
    print ''.join(random.choice(seq) for _ in range(len(seq)))

That'll print out 4 different random strings. And if you set n to 100, it'll print 100 different random strings.

You may want to write this in a function:

def print_random_strings(seq, n):
    for _ in range(n):
        print ''.join(random.choice(seq) for _ in range(len(seq)))

And then you can call it like:

print_random_strings(seq, 4)

But either way, your basic intuition is right on track.

5
  • I don't understand the aversion to __future__'s print_function. Seems like we should be encouraging beginners to use the new features. +1, otherwise.
    – jpmc26
    Commented Apr 29, 2015 at 0:42
  • @jpmc26: Well, I'd much rather people just learned Python 3 in the first place. But if someone is learning 2.7, it's presumably because they're using a book, online tutorial, class, or whatever that's geared to Python 2, which means using Python 3 features is just going to confuse them in the early stages of learning, as none of the print statements their book/site/teacher gives them will work right and they'll have no idea why…
    – abarnert
    Commented Apr 29, 2015 at 0:45
  • @jpmc26: Also, just telling people "Python 3 makes this easy, Python 2 doesn't" seems like the best way to nudge them toward thinking about why they're learning Python 2, without being too obtrusive about it. Of course they may not have a choice (e.g., there's a Python 2 class as a requirement for their degree, or they're learning it to work as a junior dev maintaining a system built in Python 2, or whatever…).
    – abarnert
    Commented Apr 29, 2015 at 0:47
  • I'm a bit stuck on how I could use the loop for the first version (my newbie version of the random string). How could I add the 'for' loop (in your example you used "for _ in range(n):") to the first version? I'm not too great with nested loops.
    – Memo Smith
    Commented Apr 29, 2015 at 2:01
  • Just kidding I got it.
    – Memo Smith
    Commented Apr 29, 2015 at 2:22
1

That's exactly what random.sample is meant for:

import random
seq = 'AGAACGC'

"".join(random.sample(seq, len(seq)))
# Gives you something like: 'CGAAACG'

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