【问题标题】:Python random.choice method without repeats?没有重复的Python random.choice 方法?
【发布时间】:2015-03-18 17:23:55
【问题描述】:

我正在尝试改进这段代码,它要求用户在给定一个状态时说出州首府是什么,但我注意到有时它会重复一个状态并询问两次。

我尝试改用 random.sample,但收到错误“TypeError: Unhashable type: 'list'。这是注释掉 random.sample 的代码(但重复):

capitals_dict = {
    'Alabama': 'Montgomery',
    'Alaska': 'Juneau',
    'Arizona': 'Phoenix',
    'Arkansas': 'Little Rock',
    'California': 'Sacramento',
    'Colorado': 'Denver',
    'Connecticut': 'Hartford',
    'Delaware': 'Dover',
    'Florida': 'Tallahassee',
    'Georgia': 'Atlanta',
    'Hawaii': 'Honolulu',
    'Idaho': 'Boise',
    'Illinois': 'Springfield',
    'Indiana': 'Indianapolis',
    'Iowa': 'Des Moines',
    'Kansas': 'Topeka',
    'Kentucky': 'Frankfort',
    'Louisiana': 'Baton Rouge',
    'Maine': 'Augusta',
    'Maryland': 'Annapolis',
    'Massachusetts': 'Boston',
    'Michigan': 'Lansing',
    'Minnesota': 'St. Paul',
    'Mississippi': 'Jackson',
    'Missouri': 'Jefferson City',
    'Montana': 'Helena',
    'Nebraska': 'Lincoln',
    'Nevada': 'Carson City',
    'New Hampshire': 'Concord',
    'New Jersey': 'Trenton',
    'New Mexico': 'Santa Fe',
    'New York': 'Albany',
    'North Carolina': 'Raleigh',
    'North Dakota': 'Bismarck',
    'Ohio': 'Columbus',
    'Oklahoma': 'Oklahoma City',
    'Oregon': 'Salem',
    'Pennsylvania': 'Harrisburg',
    'Rhode Island': 'Providence',
    'South Carolina': 'Columbia',
    'South Dakota': 'Pierre',
    'Tennessee': 'Nashville',
    'Texas': 'Austin',
    'Utah': 'Salt Lake City',
    'Vermont': 'Montpelier',
    'Virginia': 'Richmond',
    'Washington': 'Olympia',
    'West Virginia': 'Charleston',
    'Wisconsin': 'Madison',
    'Wyoming': 'Cheyenne',
}

import random

states = list(capitals_dict.keys())
for i in [1, 2, 3, 4, 5]:
    state = random.choice(states)
    #state = random.sample(states, 5) 
    capital = capitals_dict[state]
    capital_guess = input('What is the capital of ' + state + '?')

    if capital_guess == capital:
        print('Correct! Nice job!')
    else:
        print('Incorrect.  The Capital of ' + state + ' is ' + capital + '.')

print('All done.')

我也尝试过像这样使用字典名称 capitals_dict:

random.sample(capitals_dict, 5)

但我得到一个不同的错误,然后发现我不能使用这样的字典。

【问题讨论】:

  • 您遇到的错误是因为您使用列表作为索引,capital = capitals_dict[state]。您可以在进入循环之前使用random.shuffle(states),这会就地打乱列表。然后,只需依次从中选择状态。
  • 过失,我不小心使用了 Python 2.. 但是,错误消息确实告诉您可以做什么。

标签: python python-3.x random


【解决方案1】:

您可以通过首先将字典传递给list() 函数来创建字典中所有键的列表,然后从该列表中采样:

sample = random.sample(list(capitals_dict), 5)

也可以传入dict.keys()字典视图:

sample = random.sample(capitals_dict.keys(), 5)

但在内部,random.sample() 也只会将其转换为序列(tuple()),因此在这里使用list() 实际上效率更高。

你遇到的异常实际上告诉你:

>>> random.sample(capitals_dict, 5)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/.../lib/python3.4/random.py", line 311, in sample
    raise TypeError("Population must be a sequence or set.  For dicts, use list(d).")
TypeError: Population must be a sequence or set.  For dicts, use list(d).
#                                                 ^^^^^^^^^^^^^^^^^^^^^^^

演示:

>>> import random
>>> capitals_dict = {
...     'Alabama': 'Montgomery',
...     'Alaska': 'Juneau',
...     'Arizona': 'Phoenix',
...     'Arkansas': 'Little Rock',
...     'California': 'Sacramento',
...     # ... elided ...
... }
>>> 
>>> random.sample(list(capitals_dict), 5)
['Maryland', 'Mississippi', 'Wisconsin', 'Texas', 'West Virginia']

将其合并到您的代码中:

随机导入

for state in random.sample(list(capitals_dict), 5):
    capital = capitals_dict[state]
    capital_guess = input('What is the capital of {}?'.format(state))

    if capital_guess == capital:
        print('Correct! Nice job!')
    else:
        print('Incorrect. The Capital of {} is {}.'.format(state, capital))

我还将您的字符串连接替换为 str.format() 调用,以将值放入字符串模板中。

【讨论】:

  • 这是我根据您的代码尝试的:states = list(capitals_dict) for i in [1, 2, 3, 4, 5]: state = random.sample(states, 5) capital = capitals_dict[state] capital_guess = input('What is the capital of ' + state + '?') if capital_guess == capital: print('Correct! Nice job!') else: print('Incorrect. The Capital of ' + state + ' is ' + capital + '.')
  • @cisconethead:但state 是一个列表。所以下一行正在执行capitals_dict[['Maryland', 'Mississippi', 'Wisconsin', 'Texas', 'West Virginia']],这将失败,因为您不能使用列表作为键。
【解决方案2】:

尝试这样做。它只是对州名称进行采样:

import random

num_queries = 5

for state in random.sample(capitals_dict.keys(), num_queries):
    capital = capitals_dict[state]

    capital_guess = input('What is the capital of ' + state + '?')

    if capital_guess == capital:
        print('Correct! Nice job!')
    else:
        print('Incorrect.  The Capital of ' + state + ' is ' + capital + '.')

print('All done.')

虽然您可以也使用:

for state in random.sample(list(capitals_dict), num_queries):

因为list(dictionary) 将隐式返回字典键的列表,但我更喜欢明确显示正在发生的事情。

【讨论】:

  • dict.keys() 调用 list(capitals_dict.keys()) 完全是多余的。您可以直接使用list(capitals_dict)
  • @Martijn:好点,但我认为使用capitals_dict.keys() 更明确。
  • 您从random.sample() 收到的错误消息是明确的;传入capitals_dict.keys() 仍然会导致tuple() 在您可以从中采样之前被调用。
  • 此外,在循环遍历字典 (for key in dictionary:) 和使用 list() 之间建立联系很重要;两者都做同样的事情,都遍历字典并获取键。
  • @Martijn:我没有收到来自random.sample() 的错误。
【解决方案3】:

如果阅读本文的任何人都想要一个像样的美国州首府测验者,我更新了代码以包括跟踪用户得分。它会按随机顺序询问所有 50 个状态,它还会让你随时跳过和退出。

capitals_dict = {
    'Alabama': 'Montgomery',
    'Alaska': 'Juneau',
    'Arizona': 'Phoenix',
    'Arkansas': 'Little Rock',
    'California': 'Sacramento',
    'Colorado': 'Denver',
    'Connecticut': 'Hartford',
    'Delaware': 'Dover',
    'Florida': 'Tallahassee',
    'Georgia': 'Atlanta',
    'Hawaii': 'Honolulu',
    'Idaho': 'Boise',
    'Illinois': 'Springfield',
    'Indiana': 'Indianapolis',
    'Iowa': 'Des Moines',
    'Kansas': 'Topeka',
    'Kentucky': 'Frankfort',
    'Louisiana': 'Baton Rouge',
    'Maine': 'Augusta',
    'Maryland': 'Annapolis',
    'Massachusetts': 'Boston',
    'Michigan': 'Lansing',
    'Minnesota': 'St. Paul',
    'Mississippi': 'Jackson',
    'Missouri': 'Jefferson City',
    'Montana': 'Helena',
    'Nebraska': 'Lincoln',
    'Nevada': 'Carson City',
    'New Hampshire': 'Concord',
    'New Jersey': 'Trenton',
    'New Mexico': 'Santa Fe',
    'New York': 'Albany',
    'North Carolina': 'Raleigh',
    'North Dakota': 'Bismarck',
    'Ohio': 'Columbus',
    'Oklahoma': 'Oklahoma City',
    'Oregon': 'Salem',
    'Pennsylvania': 'Harrisburg',
    'Rhode Island': 'Providence',
    'South Carolina': 'Columbia',
    'South Dakota': 'Pierre',
    'Tennessee': 'Nashville',
    'Texas': 'Austin',
    'Utah': 'Salt Lake City',
    'Vermont': 'Montpelier',
    'Virginia': 'Richmond',
    'Washington': 'Olympia',
    'West Virginia': 'Charleston',
    'Wisconsin': 'Madison',
    'Wyoming': 'Cheyenne',
}

import random
counterQuestions = 0 # Represents the number of questions asked to the user
counterCorrect = 0
print('Enter the name of the State Capital with proper spelling.  Enter "skip" to skip or "quit" to quit')
for state in random.sample(list(capitals_dict), 50):
    capital = capitals_dict[state]
    capital_guess = input('What is the capital of {}? '.format(state))
    if capital_guess == 'skip':
        #print('The Capital of {} is {}.'.format(state, capital)) #study mode - use comment feature to turn this on/off.
        counterQuestions = counterQuestions + 1    
        continue
    elif capital_guess == 'quit':
        break
    elif capital_guess == capital:
        print('Correct! Nice job!')
        counterCorrect = counterCorrect + 1
        counterQuestions = counterQuestions + 1
    else:
        print('Incorrect.  The Capital of {} is {}.'.format(state, capital))
        counterQuestions = counterQuestions + 1

score = (counterCorrect / counterQuestions) * 100
counterIncorrect = counterQuestions - counterCorrect
print('All done. Your score is ' + str(score) + '% correct, or ' + str(counterCorrect) + ' out of ' + str(counterQuestions) + ' (' + str(counterIncorrect) + ' incorrect)')

【讨论】:

    猜你喜欢
    • 2021-07-06
    • 2020-01-30
    • 2021-07-28
    • 2014-03-29
    • 1970-01-01
    • 1970-01-01
    • 2016-10-23
    • 2013-06-05
    • 1970-01-01
    相关资源
    最近更新 更多