简体   繁体   中英

Use a list as the key in a Python dict

I have two lists and I need to rank their elements with the Borda positional ranking. so I made this function, but I have this error:

TypeError: unhashable type: 'list'. 

As indicated by other answers The problem is that I can't use a list as the key in a dict, since dict keys need to be immutable.So I used a tuple instead, but the error remains.

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')])] 

I open the two files as list in this way

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)

Can someone help?

Use a tuple instead of lists. They can be used as keys in dictionaries. Assuming that the lists have a fixed number of elements. Ie len(list) is same for all lists and constant.

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.

Since your lists have complex elements (tuple of list of tuples of strings), they have to be converted to contain tuples of tuples of strings so they are hashable. Like this:

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'))]

OLD ANSWER If you have list1 and list2, the way to call this function is borda_sort([list1, list2]) (or borda_sort((list1, list2)) , either works the same). If your lists contain individual elements in the same order that you want to use for borda, the answer is to make a list of lists, not to zip your lists together. I think zip() doesn't do what you think it does. zip makes a list of pairs from a pair of lists, like this:

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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