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']]
脚本应该
对同一组进行排序(例如:首先对组"a"进行排序,然后是组"b"、"c"、"d")。时间越近,日期越高。
更新"排名"在每个子数组
中 预期输出:
[['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)
我可以知道如何改进它吗?
注意,这会将您的日期时间字符串转换为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']]
其他解决方案对我来说似乎太复杂了。如果你愿意,你可以使用字符串比较,而不需要使用datetime
s。
下面是一个自定义的解决方案,我拼凑在一起,似乎给出了所需的输出:
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)