2017-06-22 28 views
0

在Django項目中,我有兩個元組列表。兩個列表中的每個元組都包含(user_id, epoch_time_of_joining)對。第一個列表是所有用戶列表。第二個列表是新用戶列表,僅包含在過去24小時內加入的ID。 FYI,所有用戶列表包含新用戶列表,並且這兩個列表根據epoch_time_of_joining(它們實際上是Redis排序集)排序。例如: -根據外部參數有效地檢索和排序對象列表(Django)

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循環。用戶名單廣泛而且不斷增長,所以我更喜歡更高效的執行方式。我想知道我是否可以在不丟失排序的情況下以某種方式使用字典,但就像我之前說過的那樣,這不是我要來的。

+0

在「#ETREIEVE RELEVANT USER OBJECTS」之後的行中不能使用order_by函數嗎? –

+1

@ArpitSolanki:不能使用'order_by()'方法,因爲在這種情況下,'User'對象不包含我需要排序的相關時間屬性。因此,問題標題中的術語「外部參數」。 –

回答

0

套件將使您的生活更輕鬆。

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 = [], [] 
+0

酷,但它會幫助減少** O(n^2)**我目前因嵌套for循環而招致? –

+0

是的,它只是因爲排序。 – Dan

+0

我是否仍然需要從DB中檢索對象列表,然後通過嵌套for循環將其映射到'new_users + sorted_exist_users'上? –

0

我不太確定這是否可行。選擇所有用戶對象,然後選擇用戶配置文件,然後選擇用戶配置文件

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') 
0

使用in_bulk()可以幫助從爲O(n^2)減少處理爲O(n),因爲它返回的事實:

...將每個主鍵值的字典映射到具有給定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)) 

此外,通過map(itemgetter(0),page_obj.object_list)in_bulk()可能是另一種優化。

相關問題