从 Python 中的字典中提取不相等的随机键
Posted
技术标签:
【中文标题】从 Python 中的字典中提取不相等的随机键【英文标题】:Pull random keys from dictionary in Python that are not equal to one another 【发布时间】:2012-08-14 20:56:16 【问题描述】:所以我正在尝试通过 Python 设置多项选择测验。我对 Python 还很陌生,所以如果有更简单的方法可以做到这一点,我很抱歉。但是,在继续使用新技术之前,我正在尝试真正了解一些基础知识。
我有一本字典。在这本词典中,我想抓取 3 个随机键。我还想确保这三个键不相等(换句话说,彼此随机)。这是我目前写的代码:
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)
我很确定问题出在我的 while 循环上。我想创建一个函数,它会一直运行直到所有三个键都不同。最后,它将打印结果。有任何想法吗?提前致谢。
【问题讨论】:
只是为了帮助改进您的问题:您指的是“问题”,但不清楚运行代码时会发生什么。 【参考方案1】:你可以使用random.sample
:
>>> random.sample(word_drills, 3)
['has-a', 'attribute', 'instance']
你不需要.keys()
,对字典的迭代是对键的。
请注意,random.sample
将从您提供的列表中返回三个唯一值(即它永远不会返回 'has-a'
两次):
>>> all(len(set(random.sample(word_drills, 3))) == 3 for i in range(10**5))
True
【讨论】:
哇,我现在感觉有点头脑简单。绝对简化了我试图做的事情。不过,我确实有一个后续问题。虽然它返回了我想要的信息,但我如何将结果分配给变量 key1、key2 和 key3? 我建议您使用密钥列表本身,只需使用keys = random.sample(word_drills, 3)
,并通过keys[0]
和keys[1]
和keys[2]
访问它们。 90% 的情况下,当您在变量名中使用数字后缀时,这表明您确实想要一个列表、元组或字典。但是如果你想要三个不同的名字,你可以简单地写key1, key2, key3 = random.sample(word_drills, 3)
。
太棒了。感谢帝斯曼!还有一个快速的问题。列表是可变的吗?所以如果我一遍又一遍地运行这个,列表中的项目也应该改变?
是的,这些项目(通常;可能会偶然重复)每次都不同。但是,列表可变性有所不同,这仅意味着您可以编写 somelist[2] = 18
并更改 somelist[2]
所指的内容。你不能对元组这样做。
我想我现在确实有另一个问题,因为我正在考虑这个问题。最终,我希望我的程序不仅能抓取 3 个随机键,而且还能抓取“正确”答案的对应值之一。基本上,该程序将提供关键“值”之一作为问题。然后用户将在 3 个随机密钥之间进行选择。如果选择的键与字典中的值匹配,则用户是正确的。否则,答案将是错误的。这有意义吗?【参考方案2】:
使用random.sample
>>> import random
>>> random.sample([1,2,3,4,5,6], 3)
[4, 5, 2]
【讨论】:
【参考方案3】:也许你想试试Quiz Me 2.5?它是一个在 Python 3.x 中带有 GUI 的多项选择测验系统。
【讨论】:
【参考方案4】:正如其他人所解释的,random.sample
是做你想做的事的最佳方式。
解释为什么您的原始代码不起作用:
第一个问题,您的 while
循环存在逻辑错误 - 只要两个项目不同,它将立即结束(例如,'a' == 'a' == 'b'
为 True,循环将结束),要解决此问题,有一个几种方法:
while not (key1 != key2 != key3):
或者,set
只能包含唯一项,所以当set([key1, key2, key3])
的长度为 3 时,三个值都不同:
while len(set([key1, key2, key3]) != 3:
第二个问题,代码拒绝运行的原因:
key1
key2
key3
被定义为全局变量(key1 = ' ' are at the top-level of your
.py` 文件,不在函数中)
您可以毫无问题地在函数中查找全局变量(就像您在 while key1 == key2 ...
所做的那样)。发生错误是因为您还尝试在循环中 assign 到 key1
- 这会使 Python 的解析器感到困惑,因为您在 while key1 == ...
部分中查找全局变量,但尝试创建一个新的下一行的函数局部变量,因此它有助于引发错误。
解决这个问题的垃圾方法是这样的:
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())
然后它会按你的意愿工作,但不要那样做 - 全局变量have their uses,但这不是这种情况..
您可以轻松地从函数返回多个值,而不是使用全局变量:
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)
哦,更好的是,您可以将word_drills
作为参数传递:
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)
...您编写的函数几乎与random.sample(word_drills, 3)
相同!
【讨论】:
原代码中存在逻辑错误。一旦三个键不一样,while 循环就会结束,这与三个键不同是不一样的。例如,如果两个相同而第三个不同,它将停止尝试。'a' == 'a' == 'b'
是不是 True。此外,while not (key1 != key2 != key3):
不是修复(key1
可能等于 key3
)。【参考方案5】:
可能最简单的做法是shuffle
键:
keysShuffled = list(word_drills)
random.shuffle(keysShuffled)
然后取前3个
threeUnique = keysShuffled[:3]
【讨论】:
shuffle
在原地工作并返回 None,所以这不会像写的那样工作。不过keys = list(word_drills); random.shuffle(keys)
会起作用。【参考方案6】:
我遇到了同样的问题并写了https://github.com/robtandy/randomdict 来解决它。也许它也会帮助你。
它提供了一个 python dict 对象,但带有额外的方法,random_key、random_value 和 random_item。所有这些都具有 O(1) 的运行时间复杂度。
【讨论】:
以上是关于从 Python 中的字典中提取不相等的随机键的主要内容,如果未能解决你的问题,请参考以下文章
如何在不从参考节点获取所有数据的情况下获取 Firebase 数据库中的随机键?