我试图像facebook一样创建通知。一切正常,但我有重复。例如,action = like,url = post / 1我想获取状态= 1的所有通知 - 未读并消除动作和网址相同的重复项。你可以在下面找到我有这样的错误的代码:
错误:'列出索引超出范围'在
if n_dup[i]['url'] == n_dup[j]['url'] and n_dup[i]['action'] == n_dup[j]
def recieve_notification(request):
t = loader.get_template('notifications.html')
nots = Notification.objects.filter(recipent=request.user, status=1, pub_date__gte=datetime.datetime.now()-datetime.timedelta(days=3))
n_dup = [] #list of notifications with duplicates
for n in nots:
n_dup.append({'id':n.id, 'url':n.url, 'action':n.action})
i = len(n_dup)-1
j = len(n_dup)-1
while j>=0:
while i>=0:
if n_dup[i]['url'] == n_dup[j]['url'] and n_dup[i]['action'] == n_dup[j]['action'] and i is not j:
del n_dup[i]
i-=1
j-=1
out_n = []
for n in n_dup:
n_id = n['id']
out_n.append(Notification.objects.get(id=n_id))
c = RequestContext(request, {'notifications':out_n, 'notifications_count':len(out_n)})
return HttpResponse(t.render(c))`
也许你知道更好的方法来编写所有这些东西?
答案 0 :(得分:4)
在两个循环的第一次迭代中j == i == len(n_dup)-1
,所以n_dup[i] == n_dup[j]
。它被认为是重复的并被删除。在第二次迭代中,您将尝试访问不再存在的n_dub[len(n_dup)-1]
,因为您已将其删除。
如果我可以建议一种替代方法,那就让我们懒得让python为我们做重复检测:
class Notification:
def __init__(self, id, url, action):
self.id = id
self.url = url
self.action = action
def __eq__(self, other):
return self.url == other.url and self.action == other.action
def __hash__(self):
return hash(self.url) ^ hash(self.action)
unique_notifications = {Notification(n.id, n.url, n.action) for n in nots}
我们定义一个通知对象,其方法是比较它并计算一个哈希(这需要将它放在一个集合中),并创建一组通知。一个集永远不会包含重复,所以你现在可以遍历集合!
您还可以将此方法添加到通知对象中并直接使用它。然后你会写:
out_n = set(Notification.objects.filter(...))
奖励:该集用于删除重复的算法比您使用的算法更有效。