如何在不逐字读取的情况下交换键和值?
我需要读取一个文本文件,把里面的内容变成一个字典,然后把字典的键和值互换,再把结果写回到一个新文件里。不过我不能导入任何东西。现在我遇到的问题是,我得到的结果是把我的值拆成一个个字母,而不是完整的单词。
我的文本文件内容是:
Cloth:Stitching
Leather:Stitching,
Blacksmith:Molding
Pottery:Shaping
Metalworking:Molding
Baking:Heating
这让我很头疼,因为我不知道为什么,列表、字典和元组这些东西我总是搞不明白。
我尝试用两种方式来写我的代码:
第一种:
with open('trial.txt', 'r') as f:
fr = f.readlines()
prof = {}
for line in fr:
key , value=line.strip().split(":")
prof[key]=value
profr = {}
for key, values in prof.items():
for value in values:
if value in profr:
profr[value].append(key)
else:
profr[value]=[key]
输出结果:
{',': ['Leather'],
'H': ['Baking'],
'M': ['Blacksmith', 'Metalworking'],
'S': ['Cloth', 'Leather', 'Pottery'],
'a': ['Pottery', 'Baking'],
'c': ['Cloth', 'Leather'],
'd': ['Blacksmith', 'Metalworking'],
'e': ['Baking'],
'g': ['Cloth', 'Leather', 'Blacksmith', 'Pottery', 'Metalworking', 'Baking'],
'h': ['Cloth', 'Leather', 'Pottery'],
'i': ['Cloth',
'Cloth',
'Leather',
'Leather',
'Blacksmith',
'Pottery',
'Metalworking',
'Baking'],
'l': ['Blacksmith', 'Metalworking'],
'n': ['Cloth', 'Leather', 'Blacksmith', 'Pottery', 'Metalworking', 'Baking'],
'o': ['Blacksmith', 'Metalworking'],
'p': ['Pottery'],
't': ['Cloth', 'Cloth', 'Leather', 'Leather', 'Baking']}
第二次尝试是去掉了.items()
,让它看起来像我之前能用的代码,不过那段代码并没有读取文本文件:
with open('trial.txt', 'r') as f:
fr = f.readlines()
prof = {}
for line in fr:
key , value=line.strip().split(":")
prof[key]=value
profr = {}
for key, values in prof:
for value in values:
if value in profr:
profr[value].append(key)
else:
profr[value]=[key]
输出结果:
*** Remote Interpreter Reinitialized ***
Traceback (most recent call last):
File "D:\code\Scripts\Menu.py", line 8, in <module>
for key, values in prof:
^^^^^^^^^^^
ValueError: too many values to unpack (expected 2)
我需要怎么做才能得到我想要的输出结果:
Stitching: Cloth, Leather
Molding: Blacksmith, Metalworking
Shaping:Pottery
Heating:Baking
如果能有解释或者相关链接就太好了。不过我已经在网上查了很多,所以不确定有没有人能给我链接到我还没看到的内容。
2 个回答
对于第二个错误,你需要写成 for key, values in prof.items():
通常情况下,你可以直接把它解析成一个 defaultdict
,并把 list
作为默认值工厂。
from collections import defaultdict
profr = defaultdict(list)
with open('trial.txt', 'r') as f:
for line in f:
v, k = line.strip(', \n').split(':')
profr[k].append(v)
defaultdict(list)
这个对象的行为和字典差不多,唯一的不同是当你传入一个新键时,它会创建一个空列表,而不是抛出一个 KeyError 错误。
不过,因为你说你 不能导入任何东西,所以你可以用普通的字典和 setdefault
方法来模拟这种行为:
profr = {}
with open('trial.txt', 'r') as f:
for line in f:
v, k = line.strip(', \n').split(':')
profr.setdefault(k, []).append(v)
with open('out.txt', 'w') as fp:
for k, v_list in profr.items():
v_str = ', '.join(v_list)
fp.write(f'{k}:{v_str}\n')
字典的 setdefault(key, value)
方法的作用是:
- 如果
key
在字典中存在,它会返回这个键对应的值。 - 如果
key
不存在,它会添加这个key
,把值设置为value
,并返回这个value
。
所以在你的情况下,如果这个键不存在,就会给这个键分配一个新的空列表;同时返回这个空列表,这样我们就可以调用 .append
方法了。
如果这个键已经存在——在这种情况下,它的值是一个列表——那么这个列表就会被返回,同样也可以调用 .append
方法。
当你的代码读取每一行文本时,你可以直接把它解析成你需要的格式。在这个例子中,因为你要交换键和值,所以你可以把每一行解析成 value:key
的形式,而不是反过来。这就是这一行的作用:
v, k = line.strip(', \n').split(':')
值在前,键在后。同时它还会清理掉多余的空格和逗号。