2017-06-21 71 views
-1

我有字典的列表,其中每個字典的形式是:在python遍歷計數對

{'A': a,'B': b} 

我想通過列表,併爲每一個(A,B)對迭代,找到一對(s),(b,a)(如果存在)。

例如,如果對於列表A = 13和B = 14的給定條目,則原始對將是(13,14)。我想搜索整個列表的列表來找到這對(14,13)。如果(14,13)發生多次,我也想記錄下來。

我想計算列表中所有原始(a,b)對的次數,補數(b,a)出現時的次數,如果是,則計算次數。要做到這一點,我有兩個for循環和一個計數器,當找到補充對。

pairs_found = 0 
for i, val in enumerate(list_of_dicts): 
    for j, vol in enumerate(list_of_dicts): 
     if val['A'] == vol['B']: 
      if vol['A'] == val['B']: 
       pairs_found += 1 

這產生比的list_of_dicts長度大一個pairs_found。我意識到這是因爲相同的配對將被過度計數。我不知道我該如何克服這種退化?

編輯的清晰度

list_of_dicts = [] 

list_of_dicts[0] = {'A': 14, 'B', 23} 
list_of_dicts[1] = {'A': 235, 'B', 98} 
list_of_dicts[2] = {'A': 686, 'B', 999} 
list_of_dicts[3] = {'A': 128, 'B', 123} 

.... 

比方說,該清單有大約10萬項。在該列表中的某處,將會有一個或多個條目,形式爲{'A'23,'B':14}。如果這是真的,那麼我想要一個櫃檯來增加一個價值。我想爲列表中的每個值做這件事。

+2

問題缺乏希望輸出的例子 – timgeb

+6

我的理解很少..你可以通過張貼示例輸入,期望的輸出*對*來詳細闡述你的循環方式,你也在比較它們自己。你可以像'if i == j:continue'那樣做,以避免這種情況 –

+0

你需要提供一個更清晰的描述什麼是期望的輸出。在這種情況下你會計算多少對:[{'A':a ,'B':b},{'A':a,'B':b},{'A':b,'B':a}]? – jadsq

回答

1

您可以創建一個包含'A'值計數器詞典和'B'鍵在所有的字典:

complements_cnt = {(dct['A'], dct['B']): 0 for dct in list_of_dicts} 

然後,所有你需要的是遍歷你的字典一個增益和增加值的 「補」:

for dct in list_of_dicts: 
    try: 
     complements_cnt[(dct['B'], dct['A'])] += 1 
    except KeyError: # in case there is no complement there is nothing to increase 
     pass 

例如有這樣的list_of_dicts

list_of_dicts = [{'A': 1, 'B': 2}, {'A': 2, 'B': 1}, {'A': 1, 'B': 2}] 

這給:

{(1, 2): 1, (2, 1): 2} 

這基本上說,{'A': 1, 'B': 2}有一個補碼(第二個)和{'A': 2, 'B': 1}有兩個(第一個和最後一個)。

解決方案是O(n)即使是100000字典,它也應該是相當快的。

注意:這與@debzsud的答案很相似。儘管我發佈了答案,但我還沒有看到它。 :(

1

你可以先創建一個列表與每個字典的元組的值:

example_dict = [{"A": 1, "B": 2}, {"A": 4, "B": 3}, {"A": 5, "B": 1}, {"A": 2, "B": 1}] 
dict_values = [tuple(x.values()) for x in example_dict] 

然後倒置每個元素的出現次數創建第二個列表:

occurrences = [dict_values.count(x[::-1]) for x in dict_values] 

最後,創建一個字典dict_values作爲鍵和occurrences作爲值:

dict(zip(dict_values, occurrences)) 

輸出:

{(1, 2): 1, (2, 1): 1, (4, 3): 0, (5, 1): 0} 

對於每個鍵,您都有倒排鍵的數量。您還可以創建字典上飛:

occurrences = {dict_values: dict_values.count(x[::-1]) for x in dict_values} 
+1

運行時間是'O(n ** 2)'(因爲'count'是'O(n)'),並且預期大小爲100 000個項目,這顯然是不可行的。 – MSeifert

1

我現在還不能100%肯定它是什麼,你想做的事,但這裏是我的猜測

pairs_found = 0 
for i, dict1 in enumerate(list_of_dicts): 
    for j, dict2 in enumerate(list_of_dicts[i+1:]): 
     if dict1['A'] == dict2['B'] and dict1['B'] == dict2['A']: 
      pairs_found += 1 

注切片上第二個for循環。這樣可以避免檢查之前已經檢查過的對(比較D1與D2是否足夠;不需要比較D2與D1)

這比O(n ** 2)好,但仍有可能改進的空間

2

這裏是我的建議:

  • 使用元組來表示你對,並以此作爲字典/組鍵。
  • 建立一套獨特的翻轉對,你會尋找。
  • 使用字典存儲的時間對出現反轉

數量然後代碼應該是這樣的:

# Create a set of unique inverted pairs  
inverted_pairs_set = {(d['B'],d['A']) for d in list_of_dicts} 
# Create a counter for original pairs 
pairs_counter_dict = {(ip[1],ip[0]):0 for ip in inverted_pairs_set] 
# Create list of pairs 
pairs_list = [(d['A'],d['B']) for d in list_of_dicts] 
# Count for each inverted pairs, how many times 
for p in pairs_list: 
    if p in inverted_pairs_set: 
     pairs_counter_dict[(p[1],p[0])] += 1