根据日期和第一个元素对列表进行排序

2024-09-27 17:54:21 发布

您现在位置:Python中文网/ 问答频道 /正文

ArrayData = [['a', 'ad', '02/10/2021  7:39:19 am', 'Rank:1'],
             ['b', 'db', '02/10/2021 6:25:20 am', 'Rank:2'],
             ['a', 'sd', '02/10/2021  5:39:19 am', 'Rank:3'],
             ['b', 'esas', '02/10/2021 6:25:20 am', 'Rank:1'],
             ['a', 'aser', '02/10/2021  9:39:19 am', 'Rank:2'],
             ['d', 'ssss', '02/10/2021  11:39:19 am', 'Rank:1']]

剧本应该

  1. 根据时间对同一组进行排序(例如,首先对组“a”进行排序,然后对组“b”、“c”、“d”)进行排序。最近的时间和日期排名更高

  2. 更新每个子阵列中的“秩”

预期产出:

[['d', 'ssss', '02/10/2021  11:39:19 am', 'Rank:1'],
 ['b', 'esas', '03/10/2021 6:25:20 am', 'Rank:2'],
 ['b', 'db', '02/10/2021 6:25:20 am', 'Rank:1'],
 ['a', 'aser', '02/10/2021  9:39:19 am', 'Rank:3'],
 ['a', 'ad', '02/10/2021  7:39:19 am', 'Rank:2'],
 ['a', 'sd', '02/10/2021  5:39:19 am', 'Rank:1']]

这是我目前写的剧本

import operator
result = sorted(ArrayData, key=operator.itemgetter(2), reverse=True)
print(result)

我可以知道如何改进它吗


Tags: importdb排序时间resultsdamoperator
2条回答

其他的解决方案对我来说太复杂了。如果需要,可以使用字符串比较,而不必求助于datetimes

下面是我装配在一起的一个定制解决方案,它似乎提供了所需的输出:

from collections import defaultdict
from pprint import pprint
from typing import DefaultDict, List


array_data = [['d', 'ssss', '11-04-20', 'Rank:1'],
              ['a', 'ad', '10-13-20', 'Rank:1'],
              ['b', 'db', '12-13-20', 'Rank:2'],
              ['a', 'sd', '05-13-20', 'Rank:3'],
              ['b', 'esas', '12-14-20', 'Rank:1'],
              ['a', 'aser', '12-13-20', 'Rank:2']]


final_array = []
group_to_data: DefaultDict[str, List[List[str]]] = defaultdict(list)

for data in array_data:
    group_to_data[data[0]].append(data)


def sort_fn(x):
    """Sort by group, then by date"""
    month, day, year = x[2].split('-')
    return f'{year}{month}{day}'


for _, data in sorted(group_to_data.items(), reverse=True):
    # sorts sub-list for each group
    data.sort(key=sort_fn)

    # iterating over data in reverse order, since that's how we want it in
    # final result
    for i in range(len(data) - 1, -1, -1):
        new_rank = f"Rank:{i + 1}"
        item = data[i]
        item[-1] = new_rank
        final_array.append(item)

pprint(final_array)

请注意,这会将日期时间字符串转换为datetime.datetime对象。这可能是可取的,也可能不是可取的,但如果您计划执行涉及这些日期的任何其他操作,则至少建议您这样做。如果您真的希望它们作为字符串,请参阅注释的代码行

另外请注意,我假设您的日期为dd/mm/yyyy。如果它们是mm/dd/yyyy,则需要在DATETIME_FORMAT中切换%d%m

import datetime
import itertools
from operator import itemgetter as get


# Assumes day/month/year, switch %d and %m if not
DATETIME_FORMAT = "%d/%m/%Y %I:%M:%S %p"


def parse_datetimes(data: list) -> list:
    result = []
    for first, second, timestamp, rank in data:
        timestamp = datetime.datetime.strptime(timestamp, DATETIME_FORMAT)
        result.append([first, second, timestamp, rank])
    return result


def custom_sort(data: list) -> list:
    # Convert datetime strings to datetime objects, then sort by first element
    sorted_data = sorted(parse_datetimes(data), key=get(0), reverse=True)

    # Re-rank each group sorted by date
    result = []
    for _, group in itertools.groupby(sorted_data, key=get(0)):
        ranked_group = []
        sorted_group = sorted(group, key=get(2))
        for rank, (*item, _) in enumerate(sorted_group, 1):
            # item[2] = item[2].strftime(DATETIME_FORMAT)
            ranked_group.append([*item, f"Rank:{rank}"])
        result.extend(ranked_group[::-1])
    return result

演示:

>>> custom_sort(ArrayData)
[['d', 'ssss', datetime.datetime(2021, 10, 2, 11, 39, 19), 'Rank:1'],
 ['b', 'esas', datetime.datetime(2021, 10, 2, 6, 25, 20), 'Rank:2'],
 ['b', 'db', datetime.datetime(2021, 10, 2, 6, 25, 20), 'Rank:1'],
 ['a', 'aser', datetime.datetime(2021, 10, 2, 9, 39, 19), 'Rank:3'],
 ['a', 'ad', datetime.datetime(2021, 10, 2, 7, 39, 19), 'Rank:2'],
 ['a', 'sd', datetime.datetime(2021, 10, 2, 5, 39, 19), 'Rank:1']]

相关问题 更多 >

    热门问题