Python 基于具有最高相似性的值对字典列表进行排序

Python 基于具有最高相似性的值对字典列表进行排序,python,sorting,go,Python,Sorting,Go,给定以下python字典列表: results = [[{'id': '001', 'result': [0,0,0,0,1]}, {'id': '002', 'result': [1,1,1,1,1]}, {'id': '003', 'result': [0,1,1,None,None]}, {'id': '004', 'result': [0,None,None,1,0]}, {'id': '005',

给定以下python字典列表:

results = [[{'id': '001', 'result': [0,0,0,0,1]},
           {'id': '002', 'result': [1,1,1,1,1]},
           {'id': '003', 'result': [0,1,1,None,None]},
           {'id': '004', 'result': [0,None,None,1,0]},
           {'id': '005', 'result': [1,0,None,1,1]},
           {'id': '006', 'result': [0,0,0,1,1]}],
          [{'id': '001', 'result': [1,0,1,0,1]},
           {'id': '002', 'result': [1,1,1,1,1]},
           {'id': '003', 'result': [0,1,1,None,None]},
           {'id': '004', 'result': [0,None,None,1,0]},
           {'id': '005', 'result': [1,0,None,1,1]},
           {'id': '006', 'result': [1,0,1,0,1]}]
            ]
我想根据“result”的值生成一个新的排序列表(python和golang),方法是比较每组玩家(“id”)之间的结果,然后根据匹配条目的数量对其进行排序(无结果被丢弃且不被计数):

在第一轮和第二轮中,001和006有九个匹配的答案:
001=[0,0,0,0,1]006=[0,0,0,1,1]-四个匹配的答案。
在第二轮中,001和006有五个匹配的答案:
001=[1,0,1,0,1]006=[1,0,1,0,1]-五个匹配的答案

sorted_results = ['001','006','002','005','003','004']

“001”和“006”是列表中的前两项,因为它们具有最多的匹配结果-九个。

如果您按“相同结果的最多数量”对这些项目进行排序,则会得到以下结果:

['003', '004', '005', '006', '001', '002']
如果您的意思是其他(即不是“相同结果的最高数量”),请澄清您的问题。此外,您还可以简单地修改
max_idential
函数,使其根据您的相似定义进行操作

使用以下公式计算上述结果:

from collections import defaultdict


results = [{'id': '001', 'result': [0, 0, 0, 0, 1]},
           {'id': '002', 'result': [1, 1, 1, 1, 1]},
           {'id': '003', 'result': [0, 1, 1, None, None]},
           {'id': '004', 'result': [0, None, None, 1, 0]},
           {'id': '005', 'result': [1, 0, None, 1, 1]},
           {'id': '006', 'result': [0, 0, 0, 1, 1]}]


def max_identical(lst):
    counts = defaultdict(lambda: 0)
    for x in lst:
        if x is not None:
            counts[x] += 1
    return max(counts.values())


results = sorted(results, key=lambda x: max_identical(x['result']))

print [x['id'] for x in results]

寻找与您的问题非常相似的解决方案,我发现此页面:

以您的例子:

import itertools
results = [[{'id': '001', 'result': [0,0,0,0,1]},
           {'id': '002', 'result': [1,1,1,1,1]},
           {'id': '003', 'result': [0,1,1,None,None]},
           {'id': '004', 'result': [0,None,None,1,0]},
           {'id': '005', 'result': [1,0,None,1,1]},
           {'id': '006', 'result': [0,0,0,1,1]}],
          [{'id': '001', 'result': [1,0,1,0,1]},
           {'id': '002', 'result': [1,1,1,1,1]},
           {'id': '003', 'result': [0,1,1,None,None]},
           {'id': '004', 'result': [0,None,None,1,0]},
           {'id': '005', 'result': [1,0,None,1,1]},
           {'id': '006', 'result': [1,0,1,0,1]}]
          ]
这将为每一轮创建ID的all vs all比较

similarity = {}
for p1, p2 in itertools.combinations(results[0], 2):
    similarity.setdefault((p1["id"], p2["id"]), sum([1 for i in range(len(p1["result"])) if p1["result"][i] == p2["result"][i]]))
for p1, p2 in itertools.combinations(results[1], 2):
    similarity.setdefault((p1["id"], p2["id"]), 0)
    similarity[(p1["id"], p2["id"])] += sum([1 for i in range(len(p1["result"])) if p1["result"][i] == p2["result"][i]])
现在,要按匹配值对ID对进行排序,将返回ID的有序元组列表

similarity = sorted(similarity, key=lambda x:similarity[x], reverse=True)
print(similarity)
现在,为了消除重复值,只需按顺序保留每个id的第一次出现,而忽略其余的

sorted_ids = []
for tuple_id in similarity:
    if tuple_id[0] not in sorted_ids:
        sorted_ids.append(tuple_id[0])
    if tuple_id[1] not in sorted_ids:
        sorted_ids.append(tuple_id[1])

print sorted_ids

编写一个函数,根据您对“相似”的定义计算两个列表之间的相似性,这可能是一个很好的开始。002不应该先出现,然后是001,然后是006吗?编辑之后,问题变得更加复杂,除了Python代码片段之外,它现在包含一个2元组的列表,而不是以前的列表。是的,谢谢您的关注。我已经尽力澄清了。@Pacifico:那么现在它实际上应该是一个两元组的列表?我更新了我的帖子,试图澄清每个id的结果将与其他id的结果进行比较,以确定哪个id在多次迭代中具有最相同的结果。