2017-06-21 124 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