如何创建其值已设置的字典?

时间:2018-11-12 06:46:56

标签: python

我正在做一个练习,要求我建立两个词典,一个词典的键是国家名称,值是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.")

我很感谢任何能将我引向正确方向的信息。

4 个答案:

答案 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表达式将输入作为国家/地区列表,并将每个xx[0]开头为list(g)的国家/地区名称组合在一起。