You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Python Django中如何按用户按日筛选最高奖励记录

在Django环境下筛选用户每日最高奖励记录

问题描述

给定一个包含用户奖励信息的字典列表,需要筛选出每个用户每日获得的最高奖励对应的完整记录。例如user_id=4在2022年9月9日有两条奖励记录,金额分别为45.00和95.00,需保留金额最高的95.00对应的记录。

输入示例:

import datetime

my_list = [
    {'id': 1, 'user_id': 4, 'date': datetime.datetime(2022, 9, 9), 'prize': '45.00'},
    {'id': 2, 'user_id': 5, 'date': datetime.datetime(2022, 9, 5), 'prize': '85.00'},
    {'id': 3, 'user_id': 5, 'date': datetime.datetime(2022, 9, 5), 'prize': '35.00'},
    {'id': 4, 'user_id': 4, 'date': datetime.datetime(2022, 9, 9), 'prize': '95.00'},
    {'id': 5, 'user_id': 3, 'date': datetime.datetime(2022, 9, 9), 'prize': '10.00'},
    {'id': 6, 'user_id': 6, 'date': datetime.datetime(2022, 9, 5), 'prize': '15.00'}
]

期望输出:

result = [
    {'id': 2, 'user_id': 5, 'date': datetime.datetime(2022, 9, 5), 'prize': '85.00'},
    {'id': 4, 'user_id': 4, 'date': datetime.datetime(2022, 9, 9), 'prize': '95.00'},
    {'id': 5, 'user_id': 3, 'date': datetime.datetime(2022, 9, 9), 'prize': '10.00'},
    {'id': 6, 'user_id': 6, 'date': datetime.datetime(2022, 9, 5), 'prize': '15.00'}
]

解决方案

方案1:纯Python内存处理(适用于数据已加载到列表的场景)

如果数据已经是内存中的字典列表,可以通过两次遍历完成筛选:

  1. 先构建(user_id, 日期)与最高奖励金额的映射关系
  2. 再次遍历原列表,筛选出符合最高金额的记录
import datetime

my_list = [
    {'id': 1, 'user_id': 4, 'date': datetime.datetime(2022, 9, 9), 'prize': '45.00'},
    {'id': 2, 'user_id': 5, 'date': datetime.datetime(2022, 9, 5), 'prize': '85.00'},
    {'id': 3, 'user_id': 5, 'date': datetime.datetime(2022, 9, 5), 'prize': '35.00'},
    {'id': 4, 'user_id': 4, 'date': datetime.datetime(2022, 9, 9), 'prize': '95.00'},
    {'id': 5, 'user_id': 3, 'date': datetime.datetime(2022, 9, 9), 'prize': '10.00'},
    {'id': 6, 'user_id': 6, 'date': datetime.datetime(2022, 9, 5), 'prize': '15.00'}
]

# 构建用户-日期对应的最高奖励映射
max_prize_map = {}
for item in my_list:
    date_key = item['date'].date()  # 提取日期部分,忽略时分秒
    prize_val = float(item['prize'])
    key = (item['user_id'], date_key)
    # 更新最高奖励
    if key not in max_prize_map or prize_val > max_prize_map[key]:
        max_prize_map[key] = prize_val

# 筛选符合条件的记录
result = []
for item in my_list:
    date_key = item['date'].date()
    key = (item['user_id'], date_key)
    if float(item['prize']) == max_prize_map[key]:
        result.append(item)

# 查看结果
print(result)

方案2:Django ORM查询(适用于数据来自数据库的场景)

如果数据存储在Django模型中,直接用ORM聚合查询更高效,无需加载全量数据到内存:

假设模型定义如下:

from django.db import models
from django.utils import timezone

class PrizeRecord(models.Model):
    user_id = models.IntegerField()
    date = models.DateTimeField(default=timezone.now)
    prize = models.DecimalField(max_digits=10, decimal_places=2)

方法A:分组聚合+筛选

from django.db.models import Max, F

# 先获取每个用户每日的最高奖励金额
max_prizes = PrizeRecord.objects.values('user_id', 'date__date').annotate(
    max_prize=Max('prize')
)

# 构造筛选条件,匹配(user_id, 日期, 最高奖励)的组合
filter_conditions = [
    (item['user_id'], item['date__date'], item['max_prize'])
    for item in max_prizes
]

# 筛选完整记录
result = PrizeRecord.objects.filter(
    **{
        '(user_id, date__date, prize)__in': filter_conditions
    }
)

# 转成字典列表
result_list = list(result.values('id', 'user_id', 'date', 'prize'))

方法B:子查询(更简洁)

from django.db.models import Subquery, OuterRef

# 子查询:获取当前用户当前日期的最高奖励金额
subquery = PrizeRecord.objects.filter(
    user_id=OuterRef('user_id'),
    date__date=OuterRef('date__date')
).values('prize').annotate(max_prize=Max('prize')).values('max_prize')

# 筛选奖励等于最高金额的记录
result = PrizeRecord.objects.filter(prize=Subquery(subquery))
result_list = list(result.values('id', 'user_id', 'date', 'prize'))

内容的提问来源于stack exchange,提问作者Munna

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.18 12:01:02