在Python字典中使用列表作为键

7

我有两个列表,需要使用Borda位置排名对它们的元素进行排名。因此,我编写了这个函数,但是出现了以下错误:

TypeError: unhashable type: 'list'. 

正如其他答案所指出的那样,问题在于我不能在dict中使用列表作为键,因为字典键需要是不可变的。所以我使用了元组代替,但错误仍然存在。

The files of the two lists look like this
list1 = [([('diritti', 'S'), ('umani', 'A')]), ([('violazioni', 'S'), ('dei', 'E'), ('diritti', 'S'), ('umani', 'A')]), ([('forze', 'S'), ('di', 'E'), ('sicurezza', 'S')]), ([('violazioni', 'S'), ('dei', 'E'), ('diritti', 'S')]), ([('Nazioni', 'SP'), ('Unite', 'SP')]), ([('anni', 'S'), ('di', 'E'), ('carcere', 'S')])] 
list2 = [([('anni', 'S'), ('di', 'E'), ('carcere', 'S')]), ([('diritti', 'S'), ('umani', 'A')]), ([('forze', 'S'), ('di', 'E'), ('sicurezza', 'S')]), ([('violazioni', 'S'), ('dei', 'E'), ('diritti', 'S'), ('umani', 'A')]), ([('violazioni', 'S'), ('dei', 'E'), ('diritti', 'S')]), ([('Nazioni', 'SP'), ('Unite', 'SP')]), ([('uso', 'S'), ('eccessivo', 'A'), ('della', 'E'), ('forza', 'S')])] 

我以这种方式将两个文件作为列表打开:

我以这种方式将两个文件作为列表打开

list1 = codecs.open('/home/list1', 'r', 'utf-8').read()
list2 = codecs.open('/home/list2', 'r', 'utf-8').read()
li = ast.literal_eval(list1)
lii = ast.literal_eval(list2)

def borda_sort(lists):
###Borda’s positional ranking combines ranked lists using information of the ordinal ranks of the elements in each list.Given lists t1, t2, t3 ... tk, for each candidate c and list ti, the score B ti (c) is the number of candidates ranked below c in ti. So The total Borda score is B(c) = ∑ B ti (c) The candidates are then sorted by descending Borda scores. Given the lists = [ ['a', 'c'], ['b', 'd', 'a'], ['b', 'a', 'c', 'd'] ], the output will be ['b', 'a', 'c', 'd']
    scores = {}
    for l in lists:
        for idx, elem in enumerate(reversed(l)):
            if not elem in scores:
                scores[elem] = 0
            scores[elem] += idx
    return sorted(scores.keys(), key=lambda elem: scores[elem], reverse=True)

lists = zip(li, lii)
print borda_sort(lists)

有人可以帮忙吗?


列表不能作为字典的键。也许将列表转换为字符串可以解决你的问题。 - Ihor Pomaranskyy
无法将列表用作Python字典键 - 原帖链接 - Ami Tavory
也许可以用字典来镜像你的列表? - ratmatz
你说你使用了元组,但我看不到它的位置。你能告诉我们这个错误是来自哪一行吗? - cdarke
你能提供一些list1和list2的样本输入以及期望的结果吗? - cdarke
1
不相关的提示:您可以使用“json”来存储列表,而不是Python文字(“ast.literal_eval()”)。 - jfs
2个回答

2

使用元组而不是列表。它们可以作为字典中的键使用,假设列表具有固定数量的元素。即len(list)对于所有列表都相同且恒定。

scores = {}
for l in lists:
    for idx, elem in enumerate(reversed(l)):
        if not elem in scores:
            scores[tuple(elem)] = 0    #Notice that i have converted list to a tuple.
        scores[tuple(elem)] += idx     #Notice that i have converted list to a tuple.
return sorted(scores.keys(), key=lambda elem: scores[tuple(elem)], reverse=True) #Notice that i have converted list to a tuple.

追踪(Traceback)最近的调用如下: 文件“/home/”,第48行,在<module>中 print borda_sort(lists) 文件“/home/fat.py”,第42行,在borda_sort中 如果元素不在分数中,则 类型错误:不可哈希类型:'list' - sss
忘记将一个列表改为元组了。我会更新上面的代码。然而,主要的问题是你必须将所有应该是键的列表改为元组。 - NegativeFeedbackLoop
错误仍然存在:TypeError:不可哈希类型:'list' - sss

2

由于您的列表包含复杂元素(元组、列表、字符串的元组),它们必须被转换为包含元组的元组,以便进行哈希。就像这样:

list1a = [ tuple(x) for x in list1 ]
list2a = [ tuple(x) for x in list2 ]

print borda_sort([list1a, list2a])

# prints [(('diritti', 'S'), ('umani', 'A')), (('forze', 'S'), ('di', 'E'), ('sicurezza', 'S')), (('violazioni', 'S'), ('dei', 'E'), ('diritti', 'S'), ('umani', 'A')), (('anni', 'S'), ('di', 'E'), ('carcere', 'S')), (('violazioni', 'S'), ('dei', 'E'), ('diritti', 'S')), (('Nazioni', 'SP'), ('Unite', 'SP')), (('uso', 'S'), ('eccessivo', 'A'), ('della', 'E'), ('forza', 'S'))]

旧答案 如果您有list1和list2,调用此函数的方法是borda_sort([list1,list2])(或borda_sort((list1,list2)),两者都可以)。如果您的列表包含按您要使用的borda顺序排列的单个元素,则答案是制作一个列表,而不是将列表合并。我认为zip()并不像你想象的那样工作。zip会从一对列表中产生一对对组成的列表,就像这样:

>>> zip((1, 2, 3), ('a', 'b', 'c'))
[(1, 'a'), (2, 'b'), (3, 'c')]

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接