5

I'm trying to create a function that takes two lists and selects an element at random from each of them. Is there any way to do this using the random.seed function?

1
  • Deterministically (pseudorandomly) or totally randomly? Consider whether you want to keep two separate RNGs, one for each list? Commented Dec 1, 2011 at 18:06

3 Answers 3

21

You can use random.choice to pick a random element from a sequence (like a list).

If your two lists are list1 and list2, that would be:

a = random.choice(list1)
b = random.choice(list2)

Are you sure you want to use random.seed? This will initialize the random number generator in a consistent way each time, which can be very useful if you want subsequent runs to be identical but in general that is not desired. For example, the following function will always return 8, even though it looks like it should randomly choose a number between 0 and 10.

>>> def not_very_random():
...     random.seed(0)
...     return random.choice(range(10))
... 
>>> not_very_random()
8
>>> not_very_random()
8
>>> not_very_random()
8
>>> not_very_random()
8
Sign up to request clarification or add additional context in comments.

1 Comment

I give an OO version of this below (inherit from list and define a method getranditem()). It's not very OO to start calling random.seed(), so that's best wrapped in the __init__() or seed() methods of an object.
1

Note: @F.J's solution is much less complicated and better.


Use random.randint to pick a pseudo-random index from the list. Then use that index to select the element:

>>> import random as r
>>> r.seed(14)   # used random number generator of ... my head ... to get 14
>>> mylist = [1,2,3,4,5]
>>> mylist[r.randint(0, len(mylist) - 1)]

You can easily extend this to work on two lists.

Why do you want to use random.seed?


Example (using Python2.7):

>>> import collections as c
>>> c.Counter([mylist[r.randint(0, len(mylist) - 1)] for x in range(200)])
Counter({1: 44, 5: 43, 2: 40, 3: 39, 4: 34})

Is that random enough?

Comments

-1

I totally redid my previous answer. Here is a class which wraps a random-number generator (with optional seed) with the list. This is a minor improvement over F.J.'s, because it gives deterministic behavior for testing. Calling choice() on the first list should not affect the second list, and vice versa:

class rlist ():
    def __init__(self, lst, rg=None, rseed=None):

        self.lst = lst

        if rg is not None:
            self.rg = rg
        else:
            self.rg = random.Random()
            if rseed is not None:
                self.rg.seed(rseed)

    def choice(self):
         return self.rg.choice(self.lst)

if __name__ == '__main__':
    rl1 = rlist([1,2,3,4,5], rseed=1234)
    rl2 = rlist(['a','b','c','d','e'], rseed=1234)

    print 'First call:'
    print rl1.choice(),rl2.choice()
    print 'Second call:'
    print rl1.choice(),rl2.choice()

6 Comments

'Using objects' is not the same as 'object-oriented'. There's nothing theoretically wrong with this solution, but practically it's far more complicated than F.J's. And for what benefit?
@Matt: it's object-oriented when it only allows you do operations that are meaningful. What if you used the wrong RNG on the wrong list? what if you seeded the wrong RNG then used the one for the other list? etc. (I wrote code which also wraps an individual RNG inside the list but didn't post it yet.)
Just noticed because of your edit, but are you sure it is a good idea to shadow random.choice() with your .choice(), especially if you are trying to avoid confusion.
@beroe: however at least I'm not shadowing random.choice(). rlist.choice() is different.
@Matt Fenwick: Totally rewrote the answer to wrap an individual RNG with each list, and simplify.
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.