【问题标题】:Pull random keys from dictionary in Python that are not equal to one another从 Python 中的字典中提取不相等的随机键
【发布时间】: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 循环上。我想创建一个函数,它会一直运行直到所有三个键都不同。最后,它将打印结果。有任何想法吗?提前致谢。

【问题讨论】:

  • 只是为了帮助改进您的问题:您指的是“问题”,但不清楚运行代码时会发生什么。

标签: python function dictionary python-2.7


【解决方案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 ... 所做的那样)。发生错误是因为您还尝试在循环中 assignkey1 - 这会使 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) 的运行时间复杂度。

      【讨论】:

        猜你喜欢
        • 2013-09-28
        • 1970-01-01
        • 2023-03-10
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2016-05-15
        • 2021-05-25
        • 2021-09-26
        相关资源
        最近更新 更多