[英]Sort list of lists based on date and first element
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']]
The script should脚本应该
Sort the same group (eg. sort group 'a' first, followed by group 'b', 'c', 'd') base on the time.根据时间对同一组进行排序(例如,首先对“a”组进行排序,然后是“b”、“c”、“d”组)。 More recent times and dates have higher ranks.
最近的时间和日期具有更高的排名。
Update the "rank" in each subarray更新每个子数组中的“排名”
Expected output:预计 output:
[['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']]
This is the current script I wrote这是我写的当前脚本
import operator
result = sorted(ArrayData, key=operator.itemgetter(2), reverse=True)
print(result)
May I know how to improve it?我可以知道如何改进它吗?
Note that this converts your datetime strings to datetime.datetime
objects.请注意,这会将您的日期时间字符串转换为
datetime.datetime
对象。 This may or may not be desirable, but is at least recommended if you plan on doing any other operations involving those dates.这可能是可取的,也可能不是可取的,但如果您计划进行涉及这些日期的任何其他操作,至少建议这样做。 If you really want them as strings, see the commented line of code.
如果您确实希望将它们作为字符串,请参阅代码的注释行。
Note also that I'm assuming that your dates are dd/mm/yyyy
.另请注意,我假设您的日期是
dd/mm/yyyy
。 If they are mm/dd/yyyy
instead, you'll need to switch the %d
and %m
in DATETIME_FORMAT
.如果它们是
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
Demo:演示:
>>> 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']]
The other solutions seemed too complicated to me.其他解决方案对我来说似乎太复杂了。 If you want you can use string comparison without resorting to
datetime
s.如果你愿意,你可以使用字符串比较而不求助于
datetime
s。
Here's a custom solution I rigged together that seems to give the desired output:这是我组装在一起的自定义解决方案,似乎可以提供所需的 output:
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)
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.