Python 根据外部参数高效地检索和排序对象列表(Django)
在Django项目中,我有两个元组列表。两个列表中的每个元组都包含一个用户标识,即加入对的历元时间。第一个列表是所有用户的列表。第二个列表是新用户列表,仅包含在过去24小时内加入的ID。仅供参考,所有用户的列表也包含新用户,并且两个列表都根据加入的历元时间进行排序,它们实际上是Redis排序集。例如:Python 根据外部参数高效地检索和排序对象列表(Django),python,django,Python,Django,在Django项目中,我有两个元组列表。两个列表中的每个元组都包含一个用户标识,即加入对的历元时间。第一个列表是所有用户的列表。第二个列表是新用户列表,仅包含在过去24小时内加入的ID。仅供参考,所有用户的列表也包含新用户,并且两个列表都根据加入的历元时间进行排序,它们实际上是Redis排序集。例如: all_users = [('16', 1489044722.035625), ('5', 1489561316.306984), ('104', 1498151886.155885), ('3'
all_users = [('16', 1489044722.035625), ('5', 1489561316.306984), ('104', 1498151886.155885), ('3', 1498158931.476488), ('2', 1498158953.978909)]
new_users = [('3', 1498158931.476488), ('2', 1498158953.978909)]
任务是通过Django ORM获得所有用户对象的统一对象列表,以便首先按最新用户排序。当它们膨胀超过100时,我还必须对结果进行分页。最后,我必须跟踪这个统一列表中的最新用户,以便在界面中在他们面前显示一个新标签
完成上述任务最有效的方法是什么?我还没能全神贯注地高效地做这件事。我目前正在尝试:
# COMBINE THE TWO LISTS, DROP TIME, BUT KEEP SORTING INTACT
combined_users = []
for (user_id,time) in all_users:
if (user_id,time) in new_users:
combined_users.append((user_id,1))
else:
combined_users.append((user_id,0))
# GET TUPLE LIST RELEVANT FOR CURRENT PAGE
page_obj = get_page_obj(page_num,combined_users,100)
#RETRIEVE RELEVANT USER OBJECTS
user_objs = User.objects.select_related('userprofile').filter(id__in=[user[0] for user in page_obj.object_list])
# USING NESTED FOR LOOPS TO CREATE FINAL LIST
users = []
for (user_id,is_new) in page_obj.object_list:
for user_obj in user_objs:
if obj.id == user_id:
users.append((obj,is_new))
这是可行的,但它使用嵌套for循环。用户列表非常庞大,而且还在不断增长,所以我更喜欢一种更高效的执行方式。我不知道我是否可以在这里使用字典而不丢失排序,但就像我之前说的,我不会想到它 我不太确定这是否有效。选择所有用户对象,对其进行排序,然后选择用户配置文件
user_objs = User.objects.filter(id__in=[user[0] for user in page_obj.object_list]).order_by('some_param')
user_profile_obj = user_objs.select_related('userprofile')
布景会让你的生活更轻松
existing_users = set(all_users) - set(new_users) # fast but you lose order
sorted_exist_users = ((i[0], False) for i in sorted(existing_users, key=lambda x: x[1]))
new_users = (i[0], True for i in new_users)
batch = []
is_new_flags = []
for i, idx, is_new in enumerate(itertools.chain(new_users, sorted_exit_users)):
if i % 100:
batch.append(idx)
is_new_flags.append(is_new)
else:
user_objs = User...filter(id_in=batch)
yield zip(user_objs, is_new_flags)
batch, is_new_flags = [], []
使用有助于将处理从^2减少到On,因为它返回:
。。。每个主键值到的实例的字典映射
具有给定ID的对象
请注意它如何更改实现的结尾:
#RETRIEVE RELEVANT USER OBJECTS
user_objs = User.objects.select_related('userprofile').in_bulk([user[0] for user in page_obj.object_list])
# USING ONE FOR LOOP TO CREATE THE FINAL LIST
users = []
for (user_id,is_new) in page_obj.object_list:
users.append((user_objs[user_id],is_new))
此外,将mapitemgetter0、page_obj.object_列表传递给in_bulk可能是另一种优化。在ETRIEVE相关用户对象后的行中,您不能使用order_by函数吗?@Arpitolanki:不能使用order_by方法,因为在这种情况下,用户对象不包含我需要按其排序的相关时间属性。因此问题标题中出现了术语“外部参数”。很酷,但它是否有助于减少由于嵌套for循环而导致的^2上的错误?是的,它是nlogn,只是因为排序。我是否仍然需要从数据库中检索对象列表,然后通过嵌套的for循环将其映射到新用户+已排序的用户?如果您按用户id进行筛选,我认为您不需要最后一步,但您认为您需要最后一步,那么这只是设置的交集。