python 循环中的计数对
Over counting pairs in python loop
我有一个字典列表,其中每个字典的形式为:
{'A': a,'B': b}
我想遍历列表并为每个 (a,b) 对找到 (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
这会生成一个 pairs_found
大于 list_of_dicts
的长度。我意识到这是因为相同的对会被多算。我不确定如何克服这种退化?
为清晰起见编辑
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}
....
假设该列表有大约 100000 个条目。在该列表的某处,将有一个或多个条目,其形式为 {'A' 23, 'B': 14}。如果这是真的,那么我想要一个计数器将其值增加一个。我想对列表中的每个值都这样做。
您可以先创建一个列表,其中每个字典的值作为元组:
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}
我仍然不能 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) 更好,但可能仍有改进空间
这是我的建议:
- 使用元组来表示您的对并将它们用作 dict/set 键。
- 构建一组您会寻找的独特倒置对。
- 使用字典存储一对出现倒置的次数
那么代码应该是这样的:
# 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
您可以创建一个计数器字典,其中包含所有字典中 'A'
和 'B'
键的值:
complements_cnt = {(dct['A'], dct['B']): 0 for dct in list_of_dicts}
然后您需要做的就是再次遍历您的字典并增加 "complements":
的值
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 的回答非常相似。在我发布答案之前我还没有看到它。 :(
我有一个字典列表,其中每个字典的形式为:
{'A': a,'B': b}
我想遍历列表并为每个 (a,b) 对找到 (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
这会生成一个 pairs_found
大于 list_of_dicts
的长度。我意识到这是因为相同的对会被多算。我不确定如何克服这种退化?
为清晰起见编辑
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}
....
假设该列表有大约 100000 个条目。在该列表的某处,将有一个或多个条目,其形式为 {'A' 23, 'B': 14}。如果这是真的,那么我想要一个计数器将其值增加一个。我想对列表中的每个值都这样做。
您可以先创建一个列表,其中每个字典的值作为元组:
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}
我仍然不能 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) 更好,但可能仍有改进空间
这是我的建议:
- 使用元组来表示您的对并将它们用作 dict/set 键。
- 构建一组您会寻找的独特倒置对。
- 使用字典存储一对出现倒置的次数
那么代码应该是这样的:
# 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
您可以创建一个计数器字典,其中包含所有字典中 'A'
和 'B'
键的值:
complements_cnt = {(dct['A'], dct['B']): 0 for dct in list_of_dicts}
然后您需要做的就是再次遍历您的字典并增加 "complements":
的值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 的回答非常相似。在我发布答案之前我还没有看到它。 :(