【问题标题】:Python Query list for oldest date最旧日期的 Python 查询列表
【发布时间】:2017-02-05 14:57:40
【问题描述】:

我的查询在列表中返回以下内容:

"Alex";"275467125";"2015-02-03 02:55:36-05";"1"
"Alex";"275467125";"2015-01-13 02:09:39-05";"1"
"Alex";"275467125";"2015-01-05 04:13:35-05";"1"
"Alex";"275467125";"2014-12-27 04:55:47-05";"1"
"Alex";"275467125";"2014-12-27 04:54:52-05";"1"
"Alex";"275467125";"2014-12-07 03:13:24-05";"1"
"Alex";"275467125";"2014-12-04 03:34:56-05";"1"
"Alex";"275467125";"2014-12-02 04:16:33-05";"1"
"Ali";"275464747";"2016-02-17 10:52:12-05";"2"
"Alladin";"275467455";"2016-03-13 06:51:52-04";"2"
"Alladin";"275467455";"2016-03-13 06:51:47-04";"2"
"Anna";"275467401";"2016-03-26 03:56:41-04";"1"
"Anna";"275467401";"2016-03-26 03:55:21-04";"1"
"Anna";"275467401";"2016-03-21 23:04:28-04";"1"
"Anna";"275467401";"2016-02-12 13:24:44-05";"1"
"Anna";"275467401";"2015-12-03 08:20:35-05";"1"
"Anna";"275467401";"2015-11-09 04:18:27-05";"1"
"Anna";"275467401";"2015-11-09 04:11:59-05";"1"
"Anna";"275467401";"2015-09-13 21:27:12-04";"1"

我想用他们拥有的最早记录创建一个人名字典。我想通了:

oldestlist = {d[0]:d[2] for d in records}

这会返回一个正确的答案,但我担心的是,如果我看到一个未按日期/时间降序格式化的列表,它将无法提供正确的答案。创建具有名称和最早日期的字典的最佳方法是什么?

【问题讨论】:

  • records 实际上是一个列表吗?如果是,它包含什么类型的数据,是["Anna" (string), id (int), record_date (datetime), some_other_int (int)]还是所有字符串?
  • 如果你给出一个实际的 python 列表,这将更容易回答。
  • @PavelGurkov 您的数据分配是正确的。它们不都是字符串
  • @roganjosh 我很抱歉它不是一个实际的列表。我从我的 pg 管理查询页面快速复制和粘贴。
  • @Echelon_One,日期的格式是什么,-x is8601 是什么格式?

标签: python list date dictionary time


【解决方案1】:

将给定的“列表”转换为实际的列表格式有点令人沮丧。如果您无法在查询本身中处理此任务,您可以尝试:

from itertools import groupby
from operator import itemgetter

lst = '''"Alex";"275467125";"2015-02-03 02:55:36-05";"1",
"Alex";"275467125";"2015-01-13 02:09:39-05";"1",
"Alex";"275467125";"2015-01-05 04:13:35-05";"1",
"Alex";"275467125";"2014-12-27 04:55:47-05";"1",
"Alex";"275467125";"2014-12-27 04:54:52-05";"1",
"Alex";"275467125";"2014-12-07 03:13:24-05";"1",
"Alex";"275467125";"2014-12-04 03:34:56-05";"1",
"Alex";"275467125";"2014-12-02 04:16:33-05";"1",
"Ali";"275464747";"2016-02-17 10:52:12-05";"2",
"Alladin";"275467455";"2016-03-13 06:51:52-04";"2",
"Alladin";"275467455";"2016-03-13 06:51:47-04";"2",
"Anna";"275467401";"2016-03-26 03:56:41-04";"1",
"Anna";"275467401";"2016-03-26 03:55:21-04";"1",
"Anna";"275467401";"2016-03-21 23:04:28-04";"1",
"Anna";"275467401";"2016-02-12 13:24:44-05";"1",
"Anna";"275467401";"2015-12-03 08:20:35-05";"1",
"Anna";"275467401";"2015-11-09 04:18:27-05";"1",
"Anna";"275467401";"2015-11-09 04:11:59-05";"1",
"Anna";"275467401";"2015-09-13 21:27:12-04";"1"'''

broken_list = lst.split(',')
stripped = [item.replace('\n', '') for item in broken_list]

rebuilt = []
for line in stripped:
    line = line.split(';')
    rebuilt.append([item.strip('"') for item in line])

# Now actually sorting this        
grouped = []
for key, group in groupby(rebuilt, key=itemgetter(0)):
    grouped.append(list(group))

sort_grouped = [sorted(item, key=itemgetter(2)) for item in grouped]
#sort_grouped = 

oldestlist = {d[0][0]:d[0][2] for d in sort_grouped}

【讨论】:

    【解决方案2】:

    您不需要对任何数据进行排序,只需使用 defaultdict 并检查当前日期与任何新日期并进行相应更新:

    s = """"Alex";"275467125";"2015-02-03 02:55:36-05";"1"
    "Alex";"275467125";"2015-01-13 02:09:39-05";"1"
    "Alex";"275467125";"2015-01-05 04:13:35-05";"1"
    "Alex";"275467125";"2014-12-27 04:55:47-05";"1"
    "Alex";"275467125";"2014-12-27 04:54:52-05";"1"
    "Alex";"275467125";"2014-12-07 03:13:24-05";"1"
    "Alex";"275467125";"2014-12-04 03:34:56-05";"1"
    "Alex";"275467125";"2014-12-02 04:16:33-05";"1"
    "Ali";"275464747";"2016-02-17 10:52:12-05";"2"
    "Alladin";"275467455";"2016-03-13 06:51:52-04";"2"
    "Alladin";"275467455";"2016-03-13 06:51:47-04";"2"
    "Anna";"275467401";"2016-03-26 03:56:41-04";"1"
    "Anna";"275467401";"2016-03-26 03:55:21-04";"1"
    "Anna";"275467401";"2016-03-21 23:04:28-04";"1"
    "Anna";"275467401";"2016-02-12 13:24:44-05";"1"
    "Anna";"275467401";"2015-12-03 08:20:35-05";"1"
    "Anna";"275467401";"2015-11-09 04:18:27-05";"1"
    "Anna";"275467401";"2015-11-09 04:11:59-05";"1"
    "Anna";"275467401";"2015-09-13 21:27:12-04";"1"
    """
    
    import  csv
    from collections import defaultdict
    
    d = defaultdict(str)
    for name,_, date, _ in csv.reader(s.splitlines(), delimiter=";"):
        if not d[name] or d[name] > date:
            d[name] = date
    
    
    from pprint import pprint as pp
    
    pp(dict(d))
    

    输出:

     {'Alex': '2014-12-02 04:16:33-05',
     'Ali': '2016-02-17 10:52:12-05',
    'Alladin': '2016-03-13 06:51:47-04',
    'Anna': '2015-09-13 21:27:12-04'}
    

    因为日期采用 y-m-d 时间 格式,所以可以安全地进行字典比较。

    【讨论】:

    • 但这肯定只有在输入是有序的情况下才有效......这就是原始帖子中的关注点?
    • @roganjosh,为什么需要订购?如果日期较新,我们只会更新用户值。
    • @PadraicCunningham,很抱歉,但您不认为时区(-04、-05,至少它们看起来像时区)会干扰吗?
    • 赞成,你教会了我一些东西,到目前为止它比我的建议更干净:)
    • @roganjosh,不用担心。
    【解决方案3】:

    我已经很接近了。我发现效果最好的答案是对我的原始代码进行了调整,但使用了 sorted() 函数。

    对于最新的我会做:

    newestlist = {d[0]:d[2] for d in sorted(records)}
    

    对于最年长的我会做:

    oldestlist = {d[0]:d[2] for d in sorted(records, reverse=True)}
    

    感谢所有回答的人。如果我使用查询集,我会记住 django 引用。

    【讨论】:

    • 但是你检查过这是什么分类吗?混淆你的记录,是什么让它按日期而不是名称排序?
    • 在我开始进一步测试后,我意识到如果我的记录一开始就混乱,我会遇到这个确切的问题。
    【解决方案4】:

    由于您需要每个 name 的最后一条记录,而不是使用 dict 显式执行此操作,因此您的查询集在名称上执行 GROUP BY。在 Django 中,您可以使用 .annotate 来做到这一点,如下所述:Django Orm get latest for each group

    因此,你的 querset 应该是这样的:

    YourModel.objects.values('name_column').annotate(latest_date=Max('date'))
    

    附加信息,您应该将order_by(-your_date_column) 与您的查询集一起使用,以确保数据始终以 desc 顺序返回,而 - 在需要列表时确保 desc 顺序。

    【讨论】:

    • OP 似乎不希望字典中的顺序,他希望字典包含名称作为键和特定用户的最旧记录时间作为值。
    • 更新了答案。感谢您的澄清:)
    猜你喜欢
    • 1970-01-01
    • 2014-02-07
    • 1970-01-01
    • 2015-02-22
    • 1970-01-01
    • 2019-09-13
    • 1970-01-01
    • 2017-06-13
    • 2013-04-11
    相关资源
    最近更新 更多