Python 按dict的最高值筛选dict列表,并考虑反向值

Python 按dict的最高值筛选dict列表,并考虑反向值,python,Python,假设我有如下数据: filter_data = [ {'sender_id': 1, 'receiver_id': 2, 'order': 1}, {'sender_id': 2, 'receiver_id': 1, 'order': 3}, {'sender_id': 3, 'receiver_id': 2, 'order': 5}, {'sender_id': 2, 'receiver_id': 3, 'order': 2}, ] # there must

假设我有如下数据:

filter_data = [
    {'sender_id': 1, 'receiver_id': 2, 'order': 1},
    {'sender_id': 2, 'receiver_id': 1, 'order': 3},
    {'sender_id': 3, 'receiver_id': 2, 'order': 5},
    {'sender_id': 2, 'receiver_id': 3, 'order': 2},
]

# there must be a better way to get max elements by reversed keys
# in list of dicts, but I think this whole another question
# so for now let this be this way. 
def get_data():
    qs_data = []
    for data in filter_data:
        for cmp_data in filter_data:
            if data['sender_id'] == cmp_data['receiver_id'] and\
                    data['receiver_id'] == cmp_data['sender_id']:
                if data['order'] > cmp_data['order']:
                    d = data
                else:
                    d = cmp_data
                if d not in qs_data:
                    qs_data.append(d)
    return qs_data
期望的输出将是

[{'order': 3, 'receiver_id': 1, 'sender_id': 2},
 {'order': 5, 'receiver_id': 2, 'sender_id': 3}]
我的代码是什么?它过滤
filter\u data
,因此我将获得
sender\u id
receiver\u id
order
值最高的项目列表,但对我来说
receiver\u id=1,sender\u id=2
sender\u id=1,receiver\u id=2

所以,我的问题是,有没有更具pythonic/更快的方法来做到这一点?或者有人可以指出改进的方向


p.S.如果有人能提出一个可以理解的标题,我将不胜感激。对不起,我的英语不好。

您可以使用字典,将发送方和接收方ID的
冻结集
映射到当前顺序最高的项目

result = {}
for item in filter_data:
    key = frozenset([item["sender_id"], item["receiver_id"]])
    if key not in result or result[key]["order"] < item["order"]:
        result[key] = item

创建一个空字典,它将收集新的最高字典。我们反复检查您的
筛选\u数据
,并检查
发送方id
接收方id
的总和,因为您说这些数据的顺序是不相关的

filter_data = [
    {'sender_id': 1, 'receiver_id': 2, 'order': 1},
    {'sender_id': 2, 'receiver_id': 1, 'order': 3},
    {'sender_id': 3, 'receiver_id': 2, 'order': 5},
    {'sender_id': 2, 'receiver_id': 3, 'order': 2},
]

new = {}
for d in filter_data:
    total = d['sender_id'] + d['receiver_id']
    if total in new:
        if d['order'] > new[total]['order']:
            new[total] = d
    else:
        new[total] = d

print new.values()
例如,它将遍历第一个字典并计算其
接收方id
发送方id
的总和(总和为3)。由于我们还没有遇到一个“发送者id”和“接收者id”合计为3的词典,因此它被添加到我们的新词典中

然而,下一本词典也有一个3的总和。我们检查它的
顺序
值是否大于上一个字典。因为它是,它覆盖了以前的字典


然后我们打印新字典的值,因为键只包含
sender\u id
receiver\u id

的和,我现在明白你的意思了吗

从itertools导入groupby
grp=groupby(筛选数据,λx:(最小值(x[“发送方id”]、x[“接收方id”]、最大值(x[“发送方id”]、x[“接收方id”]))
l=[已排序(g,key=lambda x:-x[“顺序”])[0]表示grp中的k,g]

我尽了最大的努力,但我不明白你在问什么,用列表理解法python@KalpeshDusane列表竞争只是一种句法上的糖分。我不明白你的建议。我想问的是,标准库中可能有一些函数可以使代码更短、更可读。因此,对于每对发送方和接收方,无论谁是谁,您都想要最高的顺序?您所说的“发送方id和接收方id的最大顺序值”是什么意思?好主意!使用
sender
receiver
的组合作为键。会有问题,例如当我有
sender 5
receiver 1
sender 4
receiver 2
时,因为它们会产生相同的
总数
@SardorbekImomaliev啊,我当时一定误解了这个问题。如果发生这种情况,会发生什么?您是对值求和,而不是对它们进行组合。我的意思是,发送方5和接收方1与发送方1和接收方5相同(值相反)。但是发送者5和接收者1与发送者2和接收者4不同。@SardorbekImomaliev发送者和接收者的值可能会相同吗?在我的例子中不会。因为他们在“聊天”。但总的来说,我看不出有什么不同。即使在
sender\u id==receiver\u id
时,它也应该工作。注意:要使其工作,
filter\u data
必须按要分组的键进行排序。字典中的顺序或多或少是随机的,因此它可能适用于小示例,但在其他情况下会失败。另外,为什么不使用
max
,而不是
sorted(…)[0]
?关于需要按分组对数据进行排序这一点,您是对的。关于为什么不使用max-因为我们需要检索项目本身,而不仅仅是最大顺序。您可以使用与排序
max
相同的
key
功能(只需删除
-
):
max(g,key=lambda x:x[“order”])
filter_data = [
    {'sender_id': 1, 'receiver_id': 2, 'order': 1},
    {'sender_id': 2, 'receiver_id': 1, 'order': 3},
    {'sender_id': 3, 'receiver_id': 2, 'order': 5},
    {'sender_id': 2, 'receiver_id': 3, 'order': 2},
]

new = {}
for d in filter_data:
    total = d['sender_id'] + d['receiver_id']
    if total in new:
        if d['order'] > new[total]['order']:
            new[total] = d
    else:
        new[total] = d

print new.values()