如何在不逐字读取的情况下交换键和值?

0 投票
2 回答
59 浏览
提问于 2025-04-12 20:18

我需要读取一个文本文件,把里面的内容变成一个字典,然后把字典的键和值互换,再把结果写回到一个新文件里。不过我不能导入任何东西。现在我遇到的问题是,我得到的结果是把我的值拆成一个个字母,而不是完整的单词。

我的文本文件内容是:

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 个回答

0

对于第二个错误,你需要写成 for key, values in prof.items():

2

通常情况下,你可以直接把它解析成一个 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(':')

值在前,键在后。同时它还会清理掉多余的空格和逗号。

撰写回答