简体   繁体   English

Python从CSV文件创建字典

[英]Python creating a dictionary from a csv file

I am trying to create a data dictionary from a csv file and am having some trouble. 我正在尝试从csv文件创建数据字典,但遇到了一些麻烦。 I have successfully been able to make a dictionary from two lists in my program below is my code: 我已经成功地从程序的两个列表中制作了一个字典,下面是我的代码:

playerRank = [[tournamentResults[i],rankingPoints[8]] for i in range(0,len(tournamentResults))]
dict1 = dict(playerRank)

However, when I attempt to make a dictionary out of data I have in a csv file I get an error 'TypeError: unhashable type: 'list''. 但是,当我尝试使用csv文件中的数据制作字典时,出现错误'TypeError:unhashable type:'list'。 Below is the code I tried: 下面是我尝试的代码:

totalRank = []
with open("mycsvfile.csv") as players:
    for row in csv.reader(players):
        totalRank.append(row)
    totalRank = [[totalRank[i],0] for i in range(0,len(totalRank))]
dict2 = dict(totalRank)

I don't understand why the second attempt at making a dictionary is throwing back the error whereas, the first dictionary is fine? 我不明白为什么第二次制作字典的尝试会抛出错误,而第一本字典没问题? Any help on how I could resolve this would be greatly appreciated! 我如何解决此问题的任何帮助将不胜感激!

The problem is that, as the error message says, lists are not hashable, which means you can't use them as dict keys. 问题是,如错误消息所示,列表不可散列,这意味着您不能将它们用作字典键。

In fact, the reason lists aren't hashable is to prevent you from using them as dict keys. 实际上,列表不可哈希的原因是为了防止您将它们用作dict键。 Lists are mutable, and if you mutate a key in a dict, lookup won't work anymore. 列表是可变的,并且如果您在dict中更改键,则查找将不再起作用。 (Technically, you could get around this by using a hash function based on object identity, instead of the contained values—but then either == wouldn't be useful, or it wouldn't line up with hash .) (从技术上讲,您可以通过使用基于对象标识的哈希函数而不是所包含的值来解决此问题,但是==不会有用,或者它不会与hash 。)

The usual solution is pretty simple: a tuple is just like a dict, except immutable. 通常的解决方案非常简单:除了不变之外,元组就像字典一样。 So if your keys are lists, instead of this: 因此,如果您的键是列表,请执行以下操作:

[[key, value] for ...]

… you do this: … 你做这个:

[[tuple(key), value] for ...]

And now, you can pass it to dict and everything works. 现在,您可以将其传递给dict ,一切正常。

Of course this assumes that you don't want to mutate those sequences after creating them. 当然,这假设您不想在创建序列后对其进行突变。


Meanwhile, I'm not sure why you want to use a sequence of values in the first place here, and you may in fact want something simpler. 同时,我不确定您为什么首先要使用一系列值,实际上您可能想要更简单的方法。 Your totalRank is a list of rows , and you probably only want one column in each row, not the whole thing. 您的totalRank是一个列表,您可能只希望每一行中有一 ,而不是整个内容。 In that case, just do this: 在这种情况下,只需执行以下操作:

[[totalRank[0], 0] for ...]

Or, alternatively, instead of totalRank.append(row) , do totalRank.append(row[0]) . 或者,也可以执行totalRank.append(row[0])而不是totalRank.append(row) totalRank.append(row[0])

(I'm assuming it's the first column you want here; obviously you can do row[3] or whatever if you want a different one.) (我假设这是您想要的第一列;显然,您可以执行row[3]或任何其他操作。)


While we're at it, if you're using Python 3, or Python 2.7, you can write this more readably (and efficiently, too) using a dictionary comprehension instead of a list comprehension. 当我们使用它时,如果您使用的是Python 3或Python 2.7,则可以使用字典理解而不是列表理解来更可读(也更有效)地编写此代码。 Instead of this: 代替这个:

lst = [[key, value] for ...]
dct = dict(lst)

… just do this: ……只要这样做:

dct = {key: value for ...}

Also you don't have to loop over i in range(len(lst)) if the only thing you're using i for is lst[i] ; 另外,如果您唯一使用i的是lst[i] ,则不必i in range(len(lst))遍历i in range(len(lst)) just loop over element in lst . 只是循环element in lst

Putting it all together: 放在一起:

dct2 = {tuple(rank): 0 for rank in totalRank}

… or, depending on what you wanted: …或根据您的需求:

dct2 = {rank[0]: 0 for rank in totalRank}

And one more improvement. 还有一项改进。 This: 这个:

totalRank = []
for row in csv.reader(players):
    totalRank.append(row)

Is just a verbose way of writing this: 只是一种冗长的写法:

totalRank = list(csv.reader(players))

Or, if you wanted just the first column: 或者,如果只需要第一列:

totalRank = [row[0] for row in csv.reader(players))

So we can reduce your entire loop to this: 因此,我们可以将整个循环简化为:

with open("mycsvfile.csv") as players:
    dict2 = {tuple(row): 0 for row in csv.reader(players)}

… or, again: ……或者再次:

with open("mycsvfile.csv") as players:
    dict2 = {row[0]: 0 for row in csv.reader(players)}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM