【问题标题】:Create dictionary from txt file - Debug从 txt 文件创建字典 - 调试
【发布时间】:2020-06-08 10:16:02
【问题描述】:
name,score #an example
a,1,
s,2,
d,3,
f,4,
g,5,
h,6,
j,7,
k,8,
l,9,
q,10,

这是我的文件。我想把它写成字典 (a:1,s:2...)

number_of_lines = len(open("scores.txt").readlines(  ))
d = {}
with open("scores.txt") as f:
   for line in range(number_of_lines-1):   #-1 removes the last line which is only \n
     (key, value) = line.split(",")
     d[key] = value
print(d)

我不断收到错误 AttributeError: 'int' object has no attribute 'split' 不知道为什么。

你能调试一下吗?

提前致谢,

【问题讨论】:

  • range(number_of_lines-1) 将为您提供从 0 到 number_of_lines -1 的整数,因此 line 将是一个整数,并且每个循环都会增加。所以,0, 1, 2, 3 等等,所以你不能拆分一个 int。你的意思是(key, value) = f.readline().split(",") 但我不明白你为什么关心文件的长度
  • @ChrisDoyle 感谢您的回复。然后长度是一个问题,因为那时我得到的错误只有 2,因为文件末尾还有另一行只有 \n
  • @Daniel 这与你在循环中的逻辑有关。您可以安全地执行if len(line.strip()) == 0: continue,假设您实际上将行本身放在变量line 中。请参阅下面的代码,第三个示例。应该更详细地解释这一点。

标签: python file dictionary


【解决方案1】:

range() 返回数字,而不是实际的行。由于您将range 的输出存储到lines 中,因此您将无法执行line.split(),因为line 不是实际行,而是来自range() 的值。相反,请执行以下操作:

d = {}
with open("scores.txt") as f:
    for line in f:
        key, value = line.split(",")
        d[key] = value
print(d)

如果您需要所在行的索引(您从未使用过,所以我不知道您是否需要),您可以使用enumerate 函数。

d = {}
with open("scores.txt") as f:
    for index, line in enumerate(f.readlines()):
        key, value = line.split(",")
        d[key] = value
print(d)

在 cmets 中提到,文件长度等存在问题。但这可以在 for 循环中安全地检查:

d = {}
with open("scores.txt") as f:
    for index, line in enumerate(f.readlines()):
        if len(line.strip()) <= 0: continue
        elif index == 0: continue # Skip the header or use the CSV lib
        key, value = line.split(",")
        d[key] = value
print(d)

为了更好地理解这一点,您可以在更独立的基础上使用 range 函数(如果您不喜欢阅读 docs)进行实验:

for line in range(0, 10):
    print(type(line), line)

希望这可以解决您的问题,但也可以教 range 函数的作用。

最后,考虑使用csv 模块:

import csv
with open('scores.txt') as csvfile:
    reader = csv.DictReader(csvfile, delimiter=',')
    for row in reader:
        print(row['name'], row['score'])

专业版:处理空行,为您将所有内容分类到字典中,跳过标题(或更准确地说,将它们作为每行字典中的键),最后,处理大量 CSV“魔术”你(如特殊分隔符、引号字符等)

您可以使用 csv lib 来 inline 创建最终结果,尽管它有点慢,但您最好逐行读取和处理数据,除非它是用于这样的数据库目的:

import csv
with open('scores.txt') as csvfile:
    reader = csv.DictReader(csvfile, delimiter=',')
    d = {row['name']:row['score'] for row in reader}

【讨论】:

  • 感谢您的回复。第一个例子得到错误 ValueError: too many values to unpack (expected 2) 这就是我选择 range 的原因,我会看看其他的
  • @Daniel 检查第三个示例,因为它解释了该特定问题。这与您没有检查该行是否为空有关。我还添加了一个“跳过第一 (0) 行”,因为它是一个 CSV 标题项,您可能不希望在您的 dict 中使用它。但最终,只需使用 csv 库,它会为您处理这些事情。
  • 第二个也一样
  • 最后一个给出 TypeError: 'delimiter' is an invalid keyword argument for open()
  • 了解范围的本质及其所有用途和品质是件好事
【解决方案2】:

你可以用熊猫来做这个

import pandas as pd
d = pd.read_csv('scores.txt').set_index('name')['score'].to_dict()

这适用于逗号分隔的文件,而且速度更快

【讨论】:

    【解决方案3】:

    你可以使用字典理解:

    data = """
    a,1,
    s,2,
    d,3,
    f,4,
    g,5,
    h,6,
    j,7,
    k,8,
    l,9,
    q,10,
    """
    
    dct = {key: value for line in data.split("\n") if line for key, value, *_ in [line.split(",")]}
    print(dct)
    # {'a': '1', 's': '2', 'd': '3', 'f': '4', 'g': '5', 'h': '6', 'j': '7', 'k': '8', 'l': '9', 'q': '10'}
    


    或者 - 使用您的文件(即考虑到标题):
    with open("scores.txt") as f:
        data = f.read()
        dct = {key: value 
               for line in data.split("\n")[1:] if line 
               for key, value, *_ in [line.split(",")]}
    

    【讨论】:

    • 友情提醒 OP,不要错过 Jan 在文件开头忽略 name,score #an example 的细节 - 也就是不要忘记将数据操作到上面的示例中。跨度>
    • @Torxed:感谢您发现这一点。我更新了file 部分。
    猜你喜欢
    • 2021-07-21
    • 2018-03-12
    • 2021-05-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多