我正在做一个练习,要求我建立两个词典,一个词典的键是国家名称,值是GDP。这部分工作正常。
第二本词典是我迷路的地方,因为键应该是字母A-Z,值是一组国家/地区名称。我尝试使用for循环,问题出在哪里,我在下面对此进行了评论。
如果用户输入的字符串只有一个字母(如A),则程序应打印以该字母开头的所有国家/地区。但是,当您运行该程序时,每个字母只会打印出一个国家/地区。
文本文件包含228行。即:
1:Qatar:98900
2:Liechtenstein:89400
3:Luxembourg:80600
4:Bermuda:69900
5:Singapore:59700
6:Jersey:57000
etc.
这是我的代码。
initials = []
countries=[]
incomes=[]
dictionary={}
dictionary_2={}
keywordFile = open("raw.txt", "r")
for line in keywordFile:
line = line.upper()
line = line.strip("\n")
line = line.split(":")
initials.append(line[1][0]) # first letter of second element
countries.append(line[1])
incomes.append(line[2])
for i in range(0,len(countries)):
dictionary[countries[i]] = incomes[i]
此for循环应吐出248个值(每个国家/地区一个),其中键是首字母,值是国家/地区名称。但是,它只吐出26个值(字母中的每个字母一个国家/地区)
for i in range(0,len(countries)):
dictionary_2[initials[i]] = countries[i]
print(dictionary_2)
while True:
inputS = str(input('Enter an initial or a country name.'))
if inputS in dictionary:
value = dictionary.get(inputS, "")
print("The per capita income of {} is {}.".format((inputS.title()), value ))
elif inputS in dictionary_2:
value = dictionary_2.get(inputS)
print("The countries that begin with the letter {} are: {}.".format(inputS, (value.title())))
elif inputS.lower() in "quit":
break
else:
print("Does not exit.")
print("End of session.")
我很感谢任何能将我引向正确方向的信息。
答案 0 :(得分:3)
使用defaultdict
确保首字母字典的每个值都是一个集合,然后使用add
方法。如果仅使用=
,每次都会覆盖初始键值,那么defaultdict
是使用类似以下表达式的简便方法:
if initial in dict:
dict[initial].add(country)
else:
dict[initial] = {country}
请参阅下面的完整工作示例,并请注意,我使用的是enumerate
而不是range(0,len(countries))
,
#!/usr/bin/env python3
from collections import defaultdict
initials, countries, incomes = [],[],[]
dict1 = {}
dict2 = defaultdict(set)
keywordFile = """
1:Qatar:98900
2:Liechtenstein:89400
3:Luxembourg:80600
4:Bermuda:69900
5:Singapore:59700
6:Jersey:57000
""".split("\n\n")
for line in keywordFile:
line = line.upper().strip("\n").split(":")
initials.append(line[1][0])
countries.append(line[1])
incomes.append(line[2])
for i,country in enumerate(countries):
dict1[country] = incomes[i]
dict2[initials[i]].add(country)
print(dict2["L"])
结果:
{'LUXEMBOURG', 'LIECHTENSTEIN'}
请参阅:https://docs.python.org/3/library/collections.html#collections.defaultdict
答案 1 :(得分:1)
Here's a link to a live functioning version of the OP's code online.
Python dict
对象中的键是唯一的。单个'L'
只能有一个dict
键。您的代码中发生的事情是,首先将键/值对'L':'Liechtenstein'
插入到dictionary_2
中。但是,在for
循环的后续迭代中,'L':'Liechtenstein'
被'L':Luxembourg
覆盖。这种覆盖有时被称为“破坏”。
一种获得您似乎想要的结果的方法是重写for
循环:
for i in range(0,len(countries)):
dictionary_2[initials[i]] = dictionary_2.get(initials[i], set()) | {countries[i]}
print(dictionary_2)
此外,您还必须重写下面的相关elif
语句:
elif inputS in dictionary_2:
titles = ', '.join([v.title() for v in dictionary_2[inputS]])
print("The countries that begin with the letter {} are: {}.".format(inputS, titles))
下面是上面dictionary_2[initials[i]] = dictionary_2.get(initials[i], set()) | {countries[i]}
行的完整说明:
dictionary_2.get(initials[i], set())
initials[i]
是dictionary_2
中的键,则将返回关联的值。如果initials[i]
不在字典中,它将返回空集set()
。 {countries[i]}
countries[i]
。dictionary_2.get(initials[i], set()) | {countries[i]}
|
运算符将两个集合的所有成员加在一起并返回结果。dictionary_2[initials[i]] = ...
dictionary_2
。以上代码将dictionary_2
的值设置为一组。如果要使用列表值,请改用此版本的for
循环:
for i in range(0,len(countries)):
dictionary_2[initials[i]] = dictionary_2.get(initials[i], []) + [countries[i]]
print(dictionary_2)
答案 2 :(得分:1)
dictionary2
的值应包含国家列表。一种选择是使用列表作为字典中的值。在代码中,每当要添加具有相同首字母的新国家作为值时,您都将覆盖每个键的值。
此外,您可以使用setdefault
类型的dictionary
方法。这段代码:
dictionary2 = {}
for country in countries:
dictionary2.setdefault(country[0], []).append(country)
足以优雅地创建第二个字典。
setdefault
,如果已经存在,则返回键的值(在这种情况下,键设置为国家名称的第一个字母),或者插入新的键(同样,输入的第一个字母)国家(地区))到字典中,其值是一个空集[]
。
如果要设置值(以便进行更快的查找/成员资格测试),可以使用以下几行:
dictionary2 = {}
for country in countries:
dictionary2.setdefault(country[0], set()).add(country)
答案 3 :(得分:0)
您非常接近所要查找的内容,可以在循环浏览要读取的文件raw.txt
的内容时分别填充字典。您还可以先读取文件的内容,然后执行必要的操作以填充字典。您可以使用dict comprehensions和groupby
在python中使用不错的oneliners来满足您的要求。这是一个示例:
country_per_capita_dict = {}
letter_countries_dict = {}
keywordFile = [line.strip() for line in open('raw.txt' ,'r').readlines()]
您现在在keywordFile
中拥有所有行的列表,如下所示:
['1:Qatar:98900', '2:Liechtenstein:89400', '3:Luxembourg:80600', '4:Bermuda:69900', '5:Singapore:59700', '6:Jersey:57000', '7:Libya:1000', '8:Sri Lanka:5000']
当您遍历项目时,可以split(':')
并根据需要使用[1]
和[2]
索引值。
您可以按以下方式使用字典理解:
country_per_capita_dict = {entry.split(':')[1] : entry.split(':')[2] for entry in keywordFile}
这将导致:
{'Qatar': '98900', 'Libya': '1000', 'Singapore': '59700', 'Luxembourg': '80600', 'Liechtenstein': '89400', 'Bermuda': '69900', 'Jersey': '57000'}
类似地使用groupby
中的itertools
,您可以获得:
from itertools import groupby
country_list = country_per_capita_dict.keys()
country_list.sort()
letter_countries_dict = {k: list(g) for k,g in groupby(country_list, key=lambda x:x[0]) }
这将产生所需的initial : [list of countries]
字典
{'Q': ['Qatar'], 'S': ['Singapore'], 'B': ['Bermuda'], 'L': ['Luxembourg', 'Liechtenstein'], 'J': ['Jersey']}
完整的示例如下:
from itertools import groupby
country_per_capita_dict = {}
letter_countries_dict = {}
keywordFile = [line.strip() for line in open('raw.txt' ,'r').readlines()]
country_per_capita_dict = {entry.split(':')[1] : entry.split(':')[2] for entry in keywordFile}
country_list = country_per_capita_dict.keys()
country_list.sort()
letter_countries_dict = {k: list(g) for k,g in groupby(country_list, key=lambda x:x[0]) }
print (country_per_capita_dict)
print (letter_countries_dict)
该行:
country_per_capita_dict = {entry.split(':')[1] : entry.split(':')[2] for entry in keywordFile}
遍历以下列表
['1:Qatar:98900', '2:Liechtenstein:89400', '3:Luxembourg:80600', '4:Bermuda:69900', '5:Singapore:59700', '6:Jersey:57000', '7:Libya:1000', '8:Sri Lanka:5000']
,并按:
然后将索引[1]
和[2]
上的值(分别是国家名称和人均值)作为字典。
country_list = country_per_capita_dict.keys()
country_list.sort()
此行从先前创建的词典中提取所有国家/地区的名称,并将其提取到列表中,然后按字母顺序对它们进行排序,以使groupby
正常工作。
letter_countries_dict = {k: list(g) for k,g in groupby(country_list, key=lambda x:x[0]) }
此lambda表达式将输入作为国家/地区列表,并将每个x
以x[0]
开头为list(g)
的国家/地区名称组合在一起。