繁体   English   中英

按字典最高值过滤字典列表,并考虑反转值

[英]Filter list of dicts by highest value of dict and taking reversed values into account

假设我有如下数据:

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_data因此我将获得具有sender_idreceiver_id最高order值的项目列表,但对我而言receiver_id=1, sender_id=2sender_id=1, receiver_id=2

所以我的问题是还有更多的pythonic /更快的方法吗? 或者有人可以指出改进的方向。

附注:如果有人能提出可以理解的标题,我将不胜感激。 对不起,我的英语不好。

您可以使用字典,将发送方和接收方ID的frozenset (因此顺序无关紧要)映射到当前顺序最高的项目。

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

然后,只需从字典中提取values()即可获得[{'order': 3, 'receiver_id': 1, 'sender_id': 2}, {'order': 5, 'receiver_id': 2, 'sender_id': 3}]

或收集所有项目(按发送者/接收者对分组),并使用具有max的列表理解来获得顺序最高的那些:

result = collections.defaultdict(list)
for item in filter_data:
    key = frozenset([item["sender_id"], item["receiver_id"]])
    result[key].append(item)
max_values = [max(lst, key=lambda x: x["order"]) for lst in result.values()]

我现在了解你吗?

from itertools import groupby

grp = groupby(filter_data, lambda x: (min(x["sender_id"], x["receiver_id"]), max(x["sender_id"], x["receiver_id"])))
l = [sorted(g, key = lambda x: -x["order"])[0] for k, g in grp]

创建一个空字典,它将收集新的最高字典。 我们通过你的迭代filter_data和支票金额sender_idreceiver_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()

例如,它将通过第一个词典并评估其receiver_id sender_idsender_id的总和(总和为3)。 由于我们还没有遇到sender_idreceiver_id sender_id为3的字典,因此将其添加到新字典中。

但是,下一个字典的总和为3。我们检查其order值是否大于上一个字典。 既然如此,它将覆盖以前的字典。

然后,我们打印我们的新字典的值,因为键只包含的总和sender_idreceiver_id

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM