2017-07-30 74 views
0

我試圖找到最有效的解決方案,以做到以下幾點:有效地從第二列表(元組)過濾對於一個Python列表值

我有兩個長的名單:

a = [3, 7, 89, 1, ....] #list of user_ids 
b = [(2,t1),(3,t2),(2,t3),(89,t4), ....] # list of user_id, epoch_time pairs 

目標是檢索列表a的所有成員(如果它們存在於列表b中(即列表b中每個元組的第一個成員)。請注意0​​可能存在於b中的多個元組中。

一個能夠滿足像這樣這個要求:

result = [] 
for user_id in a: 
    for uid,epoch_time in b: 
     if user_id == uid: 
      result.append(user_id) 
return result 

的問題是,有沒有辦法做到這一點的速度比爲O(n^2)?例如。例如通過重組b作爲詞典?

回答

1

您可以重新組織b作爲一本字典,正如你所說,然後檢查是否user_ida在字典可用。

a = [3, 7, 89, 1] 
b = [(2,'t1'),(3,'t2'),(2,'t3'),(89,'t4')] 
dic = {k: v for k, v in b} 
result = [x for x in a if dic.get(x)] 

dic.get(x)回報None如果x不是關鍵

+0

user_ids。 b'不是唯一的 - 注意'b'中'(2,'t1')'和'(2,'t3')'是如何出現的。這不會乾淨地翻譯成像這樣的字典,是嗎? –

+0

它會保存最後一個'key'遇到的'key',也就是'2:'t3''但是如果你使用dict只是爲了查看用戶ID是否存在,那就沒問題了 –

+0

如果你想將'b'永久轉換爲字典,您可以爲每個用戶分配一個'epoch_time'的列表並附加到它,例如:'{2:['t1','t2','t3']}' –

1

你可以使用一個允許O(1)檢查一個元素是否屬於它的集合。

result = [] 
set_a = set(a) 
for uid, epoch_time in b: 
    if uid in set_a: 
     result.append(uid) 

如果你想在結果中唯一值,可以使用一組result還有:

result = set() 
set_a = set(a) 
for uid, epoch_time in b: 
    if uid in set_a: 
     result.add(uid) 

它甚至可以在最後變成一個列表:

result = list(result) 
+0

這是不是允許重複值 –

+0

@AnthonyPham:?它會,這個問題在'並沒有真正說明什麼期望,所以我已經更新了我關於這個問題的答案 –

1

對於O(1),只需檢查值是否在列表中a開頭:

result = [] 
for uid,epoch_time in b: 
    if uid in a: 
     result.append(uid) 

如果你不想重複值,然後添加一個條件,不僅必須uida但在result已經存在:

result = [] 
for uid,epoch_time in b: 
    if uid in a and uid not in result: 
     result.append(uid) 

Try it here!

0

我會用套。既然你只是放棄了時代日期。

a = [3, 7, 89, 1, ....] 
b = [(2,t1),(3,t2),(2,t3),(89,t4), ....] 

def fn(a, b): 
    a = set(a) 
    b_uid, trash = zip(*b) 
    b_uid = set(b_uid) 
    return a.intersection(b) 

這是字典的所有速度而不涉及數值。 也修復返回類型爲任何你想要的。 (把它包在一個列表中,如果這是你想要的東西回來。