函数中的哈希错误



我遇到了这个函数的问题。我对哈希一无所知,但仍然收到有关它的错误。我的函数的目的是给出活动数量最多的人的姓名(活动是名为"Groupes"的集合中的str,函数返回一个包含名称和活动数量的集合。您可以看到成员名称在字典"membres_nom"中给出,并且使用数字来调用它们。 这是函数:

# membres_nom:dict{int:str}
membres_nom = {538:'Dimitri',802:'Elfriede',147:'Bachir', 
               125:'Amina',153:'Clovis'}


# groupes : dict[str:set[int]]
groupes = {'cinephiles':{802,125,147,153}, 
'travaux manuels':{125,802,153}, 
'cuisine':{153,147,802}, 
'sport':{153,538,802}}

def suractifs(names, group):
    """ Problème Dictionnaire Question 2
        dict{int:str} * dict[str:set[int]] -> tuple[Liste[str],int]
    """
    # nom : List[str]
    nom = []
    # nb_activites : List[int]
    nb_activites = []
    # s : List[str]
    # n : int
    # (i, j, nb_maximal) : tuple[int,int,int]
    i = 0
    nb_maximal = 0
    temp_set = set()
    # (numero, k) : tuple[int, str]
    for numero in names:
        nom.append(names[numero])
        nb_activites.append(0)
        for k in group:
            if numero in group[k]:
                nb_activites[i] += 1
        i = i + 1
    for j in range(0, len(nb_activites)):
        if nb_activites[j] > nb_maximal:
            nb_maximal = nb_activites[j]
    k = 0
    for k in range(0, len(nom)):
        if nb_activites[k] == nb_maximal:
            temp_set.add(nom[k])
    final_set = (temp_set, nb_maximal)
    return final_set

您正在尝试获取一个将集合作为元素的集合。在行final_set = {temp_set,nb_maximal}.集合元素应该是可哈希的,但集合是不可哈希的。

您可以改为返回元组或列表:final_list = [temp_set, nb_maximal] 。事实上,只需放置return temp_set, nb_maximal就会隐式构建一个元组。我认为是要走的路,更明确的返回类型,更干净等。 有关哈希性的更多信息,有很多 SO 问题,例如:在 python 中,你的意思是哈希可

哈希

顺便说一句,您似乎有一个错误,因为示例中的'Elfriede''Clovis'涉及 4 个活动,并且您的函数返回涉及 2 个活动的'Bachir''Amina'

在这里,您有函数的替代实现:

def suractifs(names, group):
    # build a list of tuples with the name in the first coordinate and 
    # the number of appearances in activities in the second coordinate
    act_list= [(n, len([a for a, s in group.iteritems() if i in s])) 
                            for i, n in names.iteritems()]
    # sort the list in decresing order of the activities
    act_list.sort(key=lambda t : -t[1])
    # get one of the names with most activities        
    a = act_list[0]
    # return only the filtered list of names that have the maximum 
    #number of activities
    return set( t[0] for t in act_list if t[1] == a[1]),  a[1]

使用 Pitto 建议的 Counter 的替代实现:

from collections import Counter
def suractifs3(names, group):
    names_in_acts = sum( (list(s) for s in group.itervalues()), [])
    act_list = Counter(names_in_acts).most_common()
    act_list.sort(key=lambda t : -t[1])
    a = act_list[0]
    return set(names[t[0]] for t in act_list if t[1] == a[1]), a[1]

我不确定我是否理解了您的代码,所以我尝试自己实现。

这是一个可能的/简单/冗长的解决方案。一个更python化的方法可能涉及使用计数器(https://pymotw.com/2/collections/counter.html(

如果您需要任何详细信息,请提出问题。

# membres_nom:dict{int:str}
membres_nom = {'Dimitri':538,'Elfriede':802,'Bachir':147, 
               'Amina':125,'Clovis':153}
# groupes : dict[str:set[int]]
groupes = {'cinephiles':{802,125,147,153}, 
'travaux manuels':{125,802,153}, 
'cuisine':{153,147,802}, 
'sport':{153,538,802}}
def highest_activity_numbers(names, group):
    # Here I create a dictionary that will contain names / activity number
    activity_count_per_name = {}
    # Using iteritems we can access the key / value in a dictionary
    # In here I access category_name and user_ids from groupes
    for category_name, user_ids in groupes.iteritems():
        # Here I access user_name and user_id from membres_nom
        # I've clearly decided for the variables name that
        # made more sense to me but you can use anything you prefer
        for user_name, user_id in membres_nom.iteritems():
            # At this point, for example, at the 1st round of the loop I
            # access 'Dimitri' and I check if he is in the users of
            # 'cinephiles'
            if user_id in user_ids:
                # If 'Dimitri' is in the list I get his current activity
                # counter and add a unit to it
                ac = activity_count_per_name.get(user_name, 0)
                activity_count_per_name[user_name] = ac + 1
    # Time to return the loot :)
    return activity_count_per_name
print highest_activity_numbers(membres_nom,groupes)

最新更新