【问题标题】:Python-Dictionary from file with two keys and multiple values来自具有两个键和多个值的文件的 Python 字典
【发布时间】:2015-02-25 00:33:02
【问题描述】:

(这个问题已经在 stackoverflow 上的几篇文章中得到解答。但是,我无法得到正确的结果,我不知道我做错了什么?)

我想从一个包含两个键和 14 个值的文本文件中创建一个字典:

data.txt:

Key1    Key2    Val1    Val2    Val3…Val14
100       a     x0      y0      z0………n0
101       a     x1      y1      z1………n1
102       b     x2      y2      z2………n2
103       b     x3      y3      z3………n3
104       c     x4      y4      z4………n4
105       c     x5      y5      z5………n5
…
140       m     xm      ym      zm………nm

字典应该是这样的:

{100: {a: [x0, y0, z0,…n0]},
101: {a: [x1, y1, z1,…n1]},
102: {b: [x2, y2, z2,…n2]},
103: {b: [x3, y3, z3,…n3]},
 …
140: {m: [xm, ym, zm,…nm]}}

我已经尝试过 Code1 和 Code2。 Code1 提供了一个非常大的字典,其中的行与附加的其他行重复。 Code2 给出错误 TypeError: unhashable type: 'slice'。

Code1:
lookupfile = open("data.txt", 'r')
lines = lookupfile.readlines()
lookup = lines[1:]   # Start the dictionary from row 1, exclude the column names
d={}
for line in lookup:
    dic = line.split()
    d.update({dic[0]: {dic[1]: dic[2:]}})
    print(d) 

Code2:
data = defaultdict(dict)
with open('data.txt', 'r') as file:
    reader = csv.DictReader(file)
    for row in reader:
        data[row['Key1']][row['Key2']]=row['Val1':]
        print (data)

我希望代码看起来像 Code2,这样我以后可以使用列名。 但是,我将不胜感激。

如果需要,我可以提供更多信息。

【问题讨论】:

    标签: python dictionary


    【解决方案1】:
    s="""Key1    Key2    Val1    Val2    Val3…Val14
    100       a     x0      y0      z0
    101       a     x1      y1      z1
    102       b     x2      y2      z2
    103       b     x3      y3      z3
    104       c     x4      y4      z4
    105       c     x5      y5      z5"""
    d  = {}
    for line in s.splitlines()[1:]:
        spl = line.split()
        d[spl[0]] ={spl[1]:spl[2:]}
    
    from pprint import pprint
    pprint(d)
    {'100': {'a': ['x0', 'y0', 'z0']},
     '101': {'a': ['x1', 'y1', 'z1']},
     '102': {'b': ['x2', 'y2', 'z2']},
     '103': {'b': ['x3', 'y3', 'z3']},
     '104': {'c': ['x4', 'y4', 'z4']},
     '105': {'c': ['x5', 'y5', 'z5']}}
    

    相同的逻辑适用于您的文件代码,以跳过文件对象上的第一行调用next。然后像上面那样简单地索引每一行。

    d = {}
    with open('data.txt', 'r') as f:
        next(f) # skip header
        for row in f:
            spl = line.split()
            # slicing using spl[2:] will give you a list of all remaining values
            d[spl[0]] = {spl[1]:spl[2:]}
    

    如果您的列之间实际上有多个空格,使用 str.split 会比使用 csv 模块更好。

    【讨论】:

    • 感谢您的快速回复。我现在确实得到了更好的结果。但是我的行数仍然比文档中的行数多,有些行被重复/附加到其他行。我的输入文件有问题吗?它是在列之间带有空格的文本。谢谢!
    • 您的文件一定有问题。这发布不会导致重复行
    • 我明白了。你能建议一种方法来创建我的输入文件吗?我已将此处发布的数据中的值复制到文本文件中,使用您的代码运行它,并且得到相同的重复行。我通常将我的文件从 Excel 中保存为“文本”。这会产生问题吗?由于缺少字符,我无法在此处发布我得到的结果。再次感谢您!
    • for ind,_ in enumerate(f):print(ind) 遍历你的文件,看看实际的行数是多少。
    • 如果您可以将链接粘贴到您的文件中也会有所帮助
    【解决方案2】:

    您正在使用DictReader,因此每个row 都是dict,并且您不能对dict 进行切片(就像您在作业的RHS 上尝试做的那样)。

    所以使用一个普通的csv.reader(所以每个row都是一个list,你可以对其进行切片)并且:

    data[row[0]][row[1]]=row[2:]
    

    【讨论】:

    • 感谢您的回复。我尝试使用简单的阅读器,但出现错误:TypeError: slice indices must be integers or None or have an index method。我的文件中没有所有整数。我应该如何处理字符串?
    • datadictdata[row[0]] 也是 - 唯一的列表和唯一的切片是 row[2:],其中索引 2 显然 一个int。所以我显示的行不能给出错误(我推荐的唯一其他更改是 Reader 代替 DictReader 也不能给出这个错误!)。您必须另外更改了其他内容(或者 not 更改了索引,正如我在此答案中清楚显示的那样)。
    • 可能是 Reader 的问题。你的意思是我应该将 reader = csv.DictReader(file) 更改为 reader = csv.Reader(file)?这没有用,所以我尝试了 reader = pd.read_csv(file, sep=""),它有效但结果错误。我很想知道您所说的 Reader 是什么意思,但我不想浪费您的时间,因为我已经在先前答案的帮助下成功运行了代码。不过,我很欣赏这个答案。谢谢。
    • 我的意思是csv.reader(file)(小写r),我也建议使用整数索引。
    • 我试过了,还是报错。所以我很确定我做错了什么。但我不想浪费你的时间,所以我会保持原样,因为我设法运行另一个版本的代码。不过,谢谢!
    猜你喜欢
    • 2014-03-20
    • 1970-01-01
    • 1970-01-01
    • 2015-12-22
    • 2011-12-09
    • 2015-10-28
    • 2011-06-09
    • 2019-07-02
    • 1970-01-01
    相关资源
    最近更新 更多