【问题标题】:TypeError: unhashable type: 'list' while writing to a file.TypeError: unhashable type: 'list' 写入文件时。
【发布时间】:2017-06-06 02:19:31
【问题描述】:

我有一个变量索引,其结构如下:

{ ‘web’: [ [1, [0, 2]], [2, [2]] ], ‘retrieval’: [ [1, [1]] ], ‘search’: [ [1, [3]], [2, [0]] ], ‘information’: [ [1, [4]] ], ‘engine’: [ [2, [1]] ], ‘ranking’: [ [2, [3]] ] }  

我需要把它写成以下格式的文件

term|docID1:pos1,pos2;docID2:pos3,pos4,pos5;…

因此,帖子列表对 ‘web’: [ [1, [0, 2]], [2, [2]] ] 将保存为:web|1:0,2;2:2

这是我正在使用的代码,

def writeIndexToFile(self):
    '''write the inverted index to the file'''
    f=open("indexFile.dat", 'w')
    for term in self.index.items():
        postinglist=[]
        for p in self.index[term]:
            docID=p[0]
            positions=p[1]
            postinglist.append(':'.join([str(docID) ,','.join(map(str,positions))]))
        print >> f, ''.join((term,'|',';'.join(postinglist)))

    f.close()

我收到以下错误:

for p in self.index[term]:
TypeError: unhashable type: 'list'

我正在使用 python 3.4。

【问题讨论】:

  • 调试 101:查看问题中涉及的变量的内容(term,对于初学者)

标签: python python-3.x


【解决方案1】:

希望这能让您了解您需要什么:

index = { 'web': [ [1, [0, 2]], [2, [2]] ], 'retrieval': [ [1, [1]] ], 'search': [ [1, [3]], [2, [0]] ], 'information': [ [1, [4]] ], 'engine': [ [2, [1]] ], 'ranking': [ [2, [3]] ] } 

with open("indexFile.dat", 'w') as f:
    for k,v in index.items():
        row = "%s|%s\n" % (k, ";".join(["%s:%s" % (i, ",".join([str(x) for x in r])) for i,r in v]))
        f.write(row)

这将创建如下文件:

engine|2:1
web|1:0,2;2:2
search|1:3;2:0
ranking|2:3
information|1:4
retrieval|1:1

使用 Python 2.7 进行测试,因此需要对您的 Python 3.4 进行一些小的调整。

【讨论】:

  • 谢谢,这适用于 python 3.4。我真的很难用印刷品。你的方法很好。
  • 太好了,很高兴它解决了您的问题,无法在 3.4 下测试,但看起来没问题。
【解决方案2】:

dict.items 返回一个元组列表,因此术语是一个 tuple 包含来自您的 dict 的键和值对,您正在尝试使用包含列表的元组作为键,因为它包含列表不是hashable,你得到错误。

如果你想分别解包键和值:

for k,v in self.index.items():
   for p in self.index[k]:

但您似乎只使用通过您在self.index[term] 的尝试判断的值,所以从一开始就使用它们:

for p in self.index.values()

如果值都有两个元素,你也可以解包:

 for k,v  in d.items():
    for doc, pos in v:
        print(doc ,pos)

输出:

1 [3]
2 [0]
2 [1]
2 [3]
1 [0, 2]
2 [2]
1 [4]
1 [1]

【讨论】:

  • 对于 doc,pos ,它给了我错误:ValueError: need more than 1 value to unpack。对于 self.index.values() 中的 p 其给出的错误位置=p[1] IndexError: list index out of range
  • @saurabhagarwal,已编辑,我的意思是来自 .items 的实际值
【解决方案3】:

元组解包将有助于在这里清理一些东西。当您有一个返回两个(或更多项)的迭代器时,您可以像这样解包这些值。

x, y = [1, 2]

您还可以进行扩展拆包,即取出第一个物品并将其与其他物品分开。

x, *y = range(10)
# [0], [1, 2, 3, 4, 5, 6, 7, 8, 9]

另外,Python 3 倾向于使用字符串格式而不是“%s”类型的东西(printf 样式格式)。在输入之前无需将整数转换为字符串。

'{}: {}'.format(1, [3, 4])
# '1: [3, 4]'

最后但并非最不重要的一点是,从 writeIndexToFile 中取出打印意味着您可以将它用于其他事情。这是生成器的一个很好的例子——一次返回一件事的函数或方法。

def format_index(index):
    for term, position_ in index.items():
        posting_list = []
        for doc_id, raw_positions in position_:
            formatted_positions = map(str, raw_positions)
            positions = ','.join(formatted_positions)

            posting = '{}:{}'.format(doc_id, positions)
            posting_list.append(posting)

        yield '{}|{}'.format(term, ';'.join(posting_list))

现在你可以使用它了

with open('file.dat', 'w') as f:
    formatted_index = format_index(index)
    f.write(';'.join(formatted_index))

【讨论】:

    猜你喜欢
    • 2015-02-11
    • 2019-10-11
    • 2020-03-27
    • 2020-05-11
    • 1970-01-01
    • 2022-12-05
    • 1970-01-01
    • 2012-11-20
    相关资源
    最近更新 更多