Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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?

like image 632
sss Avatar asked May 16 '15 09:05

sss


People also ask

Can you have list as values of dictionary Python?

Note that the restriction with keys in Python dictionary is only immutable data types can be used as keys, which means we cannot use a dictionary of list as a key .

How do you pass a list into a dictionary in Python?

You can convert a Python list to a dictionary using the dict. fromkeys() method, a dictionary comprehension, or the zip() method. The zip() method is useful if you want to merge two lists into a dictionary.

Can we use list or tuple as key in dictionary?

A tuple containing a list cannot be used as a key in a dictionary. Answer: True. A list is mutable. Therefore, a tuple containing a list cannot be used as a key in a dictionary.

Can list be hashed?

In computer science, a hash list is typically a list of hashes of the data blocks in a file or set of files. Lists of hashes are used for many different purposes, such as fast table lookup (hash tables) and distributed databases (distributed hash tables).


1 Answers

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')]
like image 57
Alex I Avatar answered Sep 29 '22 10:09

Alex I