Pull random keys from a dictionary in Python that are not equal to each other

So, I'm trying to set up a multi-choice quiz through Python. I'm new to Python, so my apologies are ahead if there is an easier way to do this. However, I am trying to understand some of the basics before moving on to new methods.

I have a dictionary. In this dictionary, I want to capture 3 random keys. I also want to make sure that these three keys are not equal (in other words, random from each other). Here is the code that I have written so far:

import random word_drills = {'class': 'Tell Python to make a new kind of thing.', 'object': 'Two meanings: the most basic kind of thing, and any instance of some thing.', 'instance': 'What you get when you tell Python to create a class.', 'def': 'How you define a function inside a class.', 'self': 'Inside the functions in a class, self is a variable for the instance/object being accessed.', 'inheritance': 'The concept that one class can inherit traits from another class, much like you and your parents.', 'composition': 'The concept that a class can be composed of other classes as parts, much like how a car has wheels.', 'attribute': 'A property classes have that are from composition and are usually variables.', 'is-a': 'A phrase to say that something inherits from another, as in a Salmon *** Fish', 'has-a': 'A phrase to say that something is composed of other things or has a trait, as in a Salmon *** mouth.'} key1 = ' ' key2 = ' ' key3 = ' ' def nodupchoice(): while key1 == key2 == key3: key1 = random.choice(word_drills.keys()) key2 = random.choice(word_drills.keys()) key3 = random.choice(word_drills.keys()) nodupchoice() print "Key #1: %s, Key #2: %s, Key #3: %s" % (key1, key2, key3) 

I am sure the problem is with my while loop. I wanted to create a function that will work until all three keys are different from each other. Finally, he will print the result. Any ideas? Thanks in advance.

+6
source share
6 answers

You can use random.sample :

 >>> random.sample(word_drills, 3) ['has-a', 'attribute', 'instance'] 

and you don’t need .keys() , dictionary iteration over keys.

Note that random.sample will return three unique values ​​from the list you supply (i.e. it will never return 'has-a' twice):

 >>> all(len(set(random.sample(word_drills, 3))) == 3 for i in range(10**5)) True 
+12
source

Use random.sample

 >>> import random >>> random.sample([1,2,3,4,5,6], 3) [4, 5, 2] 
+3
source

Probably the easiest way is to make shuffle keys:

 keysShuffled = list(word_drills) random.shuffle(keysShuffled) 

Then take the first 3

 threeUnique = keysShuffled[:3] 
0
source

Would you like to try Quiz Me 2.5 ? This is a graphical multiple-choice polling system in Python 3.x.

0
source

As others have explained, random.sample is the best way to do what you want.

To explain why your source code didn't work:

First problem: there is a logical error with your while - it will end as soon as the two elements are different (for example, 'a' == 'a' == 'b' will be True and the loop will end), to fix this, There are several ways:

 while not (key1 != key2 != key3): 

Alternatively, set can only contain unique elements, so when the length of set([key1, key2, key3]) is 3, all three values ​​are different:

 while len(set([key1, key2, key3]) != 3: 

The second problem and the reason why the code refuses to run:

key1 key2 key3 defined as global variables ( key1 = ' ' are at the top-level of your .py`, not in a function)

You can search for a global variable in a function without problems (for example, when you did while key1 == key2 ... ). The error arises because you are also trying to assign key1 in your loop - this confuses the Python parser because you are viewing the global variable in the while key1 == ... , but trying to create a new local function variable on the next line, therefore he helps make a mistake.

The tail, to fix this, looks like this:

 key1 = ' ' key2 = ' ' key3 = ' ' def nodupchoice(): global key1 global key2 global key3 while not (key1 != key2 != key3): key1 = random.choice(word_drills.keys()) key2 = random.choice(word_drills.keys()) key3 = random.choice(word_drills.keys()) 

Then it will work as you planned, but do not do this - global variables will use them , but this is not the case.

Instead of using a global variable, you can easily return multiple values ​​from a function:

 def nodupchoice(): key1 = ' ' # local variables, which are inaccessible outside this function key2 = ' ' key3 = ' ' while not (key1 != key2 != key3): key1 = random.choice(word_drills.keys()) key2 = random.choice(word_drills.keys()) key3 = random.choice(word_drills.keys()) return key1, key2, key3 key1, key2, key3 = nodupchoice() print "Key #1: %s, Key #2: %s, Key #3: %s" % (key1, key2, key3) 

Oh, and even better, you can pass in word_drills as an argument:

 def nodupchoice(things): key1 = ' ' # local variables, which are inaccessible outside this function key2 = ' ' key3 = ' ' while not (key1 != key2 != key3): key1 = random.choice(things) key2 = random.choice(things) key3 = random.choice(things) return key1, key2, key3 key1, key2, key3 = nodupchoice(word_drills) 

... and you wrote a function almost identical to the random.sample(word_drills, 3) function random.sample(word_drills, 3) !

0
source

I had this samme problem and she wrote https://github.com/robtandy/randomdict to solve this problem. Perhaps this will also help you.

It provides a python dict object, but with optional methods, random_key, random_value and random_item. All with O (1) runtime complexity.

0
source

Source: https://habr.com/ru/post/923204/


All Articles