我正在尝试使用看起来像这样的文件
AAA x 111
AAB x 111
AAA x 112
AAC x 123
...
使用字典使输出看起来像这样
{AAA: ['111', '112'], AAB: ['111'], AAC: [123], ...}
这就是我试过的
file = open("filename.txt", "r")
readline = file.readline().rstrip()
while readline!= "":
list = []
list = readline.split(" ")
j = list.index("x")
k = list[0:j]
v = list[j + 1:]
d = {}
if k not in d == False:
d[k] = []
d[k].append(v)
readline = file.readline().rstrip()
我一直在TypeError: unhashable type: 'list'
。我知道字典中的键不能是列表,但我试图将我的值变成列表而不是键。我想知道我是否在某处犯了错误。
答案 0 :(得分:39)
正如其他答案所示,错误是由k = list[0:j]
引起的,您的密钥将转换为列表。您可以尝试的一件事是重新编写代码以利用split
函数:
# Using with ensures that the file is properly closed when you're done
with open('filename.txt', 'rb') as f:
d = {}
# Here we use readlines() to split the file into a list where each element is a line
for line in f.readlines():
# Now we split the file on `x`, since the part before the x will be
# the key and the part after the value
line = line.split('x')
# Take the line parts and strip out the spaces, assigning them to the variables
# Once you get a bit more comfortable, this works as well:
# key, value = [x.strip() for x in line]
key = line[0].strip()
value = line[1].strip()
# Now we check if the dictionary contains the key; if so, append the new value,
# and if not, make a new list that contains the current value
# (For future reference, this is a great place for a defaultdict :)
if key in d:
d[key].append(value)
else:
d[key] = [value]
print d
# {'AAA': ['111', '112'], 'AAC': ['123'], 'AAB': ['111']}
请注意,如果您使用的是Python 3.x,则必须进行微调以使其正常工作。如果使用rb
打开文件,则需要使用line = line.split(b'x')
(这样可以确保使用正确的字符串类型拆分字节)。您也可以使用with open('filename.txt', 'rU') as f:
(甚至with open('filename.txt', 'r') as f:
)打开文件,它应该可以正常工作。
答案 1 :(得分:14)
您尝试使用k
(列表)作为d
的密钥。列表是可变的,不能用作字典键。
此外,由于以下行,您永远不会初始化字典中的列表:
if k not in d == False:
应该是:
if k not in d == True:
实际应该是:
if k not in d:
答案 2 :(得分:10)
注意: 该答案没有明确回答所提问题。其他答案可以做到。由于问题是特定于情境的,而提出的例外是一般性的,因此该答案指向一般情况。
哈希值只是整数,用于在字典查找期间快速比较字典键。
内部,hash()
方法调用对象的__hash__()
方法,该方法默认情况下为任何对象设置。
>>> a = [1,2,3,4,[5,6,7],8,9]
>>> set(a)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: unhashable type: 'list'
发生这种情况是因为列表内的列表是不能散列的列表。可以通过将内部嵌套列表转换为元组
来解决>>> set([1, 2, 3, 4, (5, 6, 7), 8, 9])
set([1, 2, 3, 4, 8, 9, (5, 6, 7)])
>>> hash([1, 2, 3, [4, 5,], 6, 7])
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: unhashable type: 'list'
>>> hash(tuple([1, 2, 3, [4, 5,], 6, 7]))
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: unhashable type: 'list'
>>> hash(tuple([1, 2, 3, tuple([4, 5,]), 6, 7]))
-7943504827826258506
避免此错误的解决方案是将列表重组为具有嵌套元组而不是列表。
答案 3 :(得分:4)
您获得unhashable type: 'list'
例外的原因是因为k = list[0:j]
将k
设置为列表的“切片”,这在逻辑上是另一个,通常更短的列表。你需要的只是获得列表中的第一项,如k = list[0]
所示。对于从v = list[j + 1:]
调用返回的列表的第三个元素,v = list[2]
应该只有readline.split(" ")
。
我注意到代码中存在其他一些可能的问题,我将提到一些问题。对于循环中读取的每一行,您不希望(重新)使用d
初始化d = {}
。另一个是,将变量命名为与任何内置类型相同的通常不是一个好主意,因为它会阻止您在需要时访问其中一个 - 并且对于习惯于其中的其他人而言,这会让您感到困惑。指定其中一个标准项目的名称。出于这个原因,您应该将变量list
变量重命名,以避免出现类似问题。
这是你的工作版本中的这些变化,我还简化了你所拥有的if
语句表达式,它检查键是否已经存在于字典中 - 还有更短的隐式方法来执行此操作有点像,但现在使用条件语句就好了。
d = {}
file = open("filename.txt", "r")
readline = file.readline().rstrip()
while readline:
lst = readline.split(" ") # Split into sequence like ['AAA', 'x', '111'].
k = lst[0] # First item.
v = lst[2] # Third item.
if k not in d: # New key?
d[k] = [] # Initialize its associated value to an empty list.
d[k].append(v)
readline = file.readline().rstrip()
file.close() # Done reading file.
print('d: {}'.format(d))
输出:
d: {'AAA': ['111', '112'], 'AAC': ['123'], 'AAB': ['111']}
答案 4 :(得分:0)
TypeError
正在发生,因为k
是一个列表,因为它是使用来自另一个列表k = list[0:j]
的切片创建的。这应该类似k = ' '.join(list[0:j])
,所以你有一个字符串。
除此之外,您的if
声明不正确,如Jesse的回答所述,该回复应为if k not in d
或if not k in d
(我更喜欢后者)。
您还在每次迭代时清除字典,因为d = {}
循环中有for
。
请注意,您也不应该使用list
或file
作为变量名称,因为您将屏蔽内置函数。
以下是我重写代码的方法:
d = {}
with open("filename.txt", "r") as input_file:
for line in input_file:
fields = line.split()
j = fields.index("x")
k = " ".join(fields[:j])
d.setdefault(k, []).append(" ".join(fields[j+1:]))
上面的dict.setdefault()
方法替换了代码中的if k not in d
逻辑。
答案 5 :(得分:-1)
python 3.2
with open("d://test.txt") as f:
k=(((i.split("\n"))[0].rstrip()).split() for i in f.readlines())
d={}
for i,_,v in k:
d.setdefault(i,[]).append(v)