2015-04-24 48 views
1

我有listA,其中包含如何找到一個列表,同時也是在B名單

[0, 20, 40, 60, 80, 80, 100, 120, 140, 160, 180, 200, 220, 240, 260, 280, 300, 320, 340] 

listB,其中包含

[87, 78343, 100, 38, 100, 20, 80] 

我想項目的索引以便能夠找到listA中的數字索引,這些索引也在listB中。

例如,listAlistB每股100,100,20,和80這些整數的listA指數是

[6, 6, 1, 4, 5] 

是否有一個過程,會發現這對我,所以我不必須手工做?

這與this question類似。不同之處在於我必須知道索引,即使它在任一列表中出現多次,而該鏈接上的答案僅適用於實例的第一個示例:即listB中的80位於[4]和[5]位於listA,但所描述的方法只會返回[4]。

+0

如果一個值在兩個列表中出現多次,該怎麼辦?例如,'[0,1,1,2]'和'[1,1,3,4]'?那應該是'[1,2,2]'嗎? –

回答

1

這可能是你真正想要的東西:

wanted_indexes = [index for index, value in enumerate(listA) if value in listB] 

對於示例listAlistB,這將產生

[1, 4, 5, 6] 

這給你所有項目中listA這也是該指數在listB。如果你確實想重複,那麼你可以使用這個:

dups_included = [index for b_value in listB for index, a_value in enumerate(listA) if a_value == b_value] 

這將產生你給了作爲一個例子名單:

[6, 6, 1, 4, 5] 

提升性能:

如果」再次擔心運行時間,您可以針對其中的每一項進行一些優化。對於第一個,創建一個基於listB一組,並使用 -

setB = set(listB) 
wanted_indexes = [index for index, value in enumerate(listA) if value in setB] 

看起坐是一組比他們在列表中快得多,所以除非組B是相當小的,這將給你一個表現促進。

對於帶有重複項的版本,您希望創建一個將listA中的每個值映射到它出現的索引列表的字典。然後,當您迭代listB時,可以使用此查找表,而不是遍歷listA以獲取索引。這正是Padraic did in his answer

+0

我喜歡這個解決方案,但是如果你在'set(listB)'而不是'in listB'中做的話會更有效率。 – Shashank

+0

@Shashank你不能這麼簡單 - 使用set(listB)''會每次創建一個新集。 –

+0

這是一個有效的點,但在我看來,使代碼2行進行O(n * m)計算O(n + m)是值得的折衷。那麼爲什麼不把它存儲在一個變量中呢? – Shashank

2

創建一個字典來保存所有索引,包括重複的元素,然後用列表比較增加索引的共同元素:

from collections import defaultdict 

d = defaultdict(list) 

for i, ele in enumerate(A): 
    d[ele].append(i) 

print([ele for i in B for ele in d[i] if i in d]) 
[6, 6, 1, 4, 5] 

如果我們增加了幾個80的,你可以看到它返回所有合適的索引:

A = [0, 20, 40, 60, 80, 80, 100, 80, 120, 80,140, 160, 180, 200, 220, 240, 260, 280, 300, 320, 340,21] 


B = [87, 78343, 100, 38, 100, 20, 80] 

from collections import defaultdict 

d = defaultdict(list) 

for i, ele in enumerate(A): 
    d[ele].append(i) 

print([ele for i in B for ele in d[i] if i in d]) 
[6, 6, 1, 4, 5, 7, 9, 21] 

對於大型列表,這將是非常有效的,查找和0(1),所以構建字典的成本將抵消任何合理大小的數據和規模。

有一兩件事是清楚的,如果你有兩個列表中重複條目,會發生什麼,例如:

A = [1, 2, 2, 3, 3, 4, 5] 
B = [3, 4, 3, 5] 

變爲:

[3, 4, 5 3, 4, 6] 

其中3,4因爲3是在重複出現了兩次都。

如果是這樣的話,你可以繼續在B還元素的計數:

from collections import defaultdict, Counter 

d = defaultdict(list) 
for i, ele in enumerate(A): 
    d[ele].append(i) 

cn = Counter(B) 
l = [] 
for i in B: 
    if i in d: 
     val = d[i] 
     l.extend(val.pop(0) if len(val) > 1 and cn[i] > 1 else ele for ele in val) 
print(l) 
[3, 5, 4, 6] 

不過,如果項目出現B中3次,你會得到一個索引的第一個值最後出現:

A = [1, 2, 2, 3, 3, 4, 5] 
B = [3, 4, 3, 5, 3] 
[3, 5, 4, 6, 4] 
-1

幾乎類似於vguzmanp answer

r=[] 
for i in range(len(listA)): 
    for _ in range(listB.count(listA[i])): 
     r.append(i) 
0

所以RT答: -

>>>reduce(lambda x, y: x+y, [[index for index,value in enumerate(listA) if item == value] for item in listB if item in listA]) 
[6, 6, 1, 4, 5] 

龍答: -

>>>def get_common_items_index(listA,listB): 
     result = [] 
     common_items = [item for item in listB if item in listA] 
     for each_item in common_items: 
      for index,value in enumerate(listA): 
       if value == each_item: 
        result.append(index) 
     return result 

>>> get_common_items_index(listA,listB) 
[6, 6, 1, 4, 5] 
0

您需要自定義索引功能在listA返回x的發生的所有指數:

def all_indices(l, x): 
    return [i for i, y in enumerate(l) if x == y] 

現在將其映射到listB,並連接結果:

>>> sum(map(lambda x: all_indices(listA, x), listB), []) 
[6, 6, 1, 4, 5] 
相關問題