我遇到了这个函数的问题。我对哈希一无所知,但仍然收到有关它的错误。我的函数的目的是给出活动数量最多的人的姓名(活动是名为"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)