I have a list of of tuples that represent different times
timeList = [('4', '12', 'PM'), ('8', '23', 'PM'), ('4', '03', 'AM'), ('1', '34', 'AM'),
('12', '48', 'PM'), ('4', '13', 'AM'), ('11', '09', 'AM'), ('3', '12', 'PM'),
('4', '10', 'PM')]
I want to return the max from the list, after some searching I realized I could use the key in max to search by the AM or PM first.
print(max(timeList, key = operator.itemgetter(2)))
When I run this however, I’m getting the wrong max ('4', '12', 'PM')
I thought about it, and not only does it not make sense, given that 8:23 should be max, but I also realized that 12:48 would probably return max since it’s a PM and also technically greater than 8 in my search.
That being said, how might I get this max to find the latest possible time, given formatting of the list can not be changed.
Solution:
Just define an appropriate key-function. You want int(hour), int(minute) and 'PM' already sorts lexicographically higher than "AM", but it should be considered first, so. Also, you need to take the hours modulus 12, so that 12 sorts less than other numbers, within a pm/am:
In [39]: timeList = [('4', '12', 'PM'), ('8', '23', 'PM'), ('4', '03', 'AM'), ('1', '34', 'AM'),
...: ('12', '48', 'PM'), ('4', '13', 'AM'), ('11', '09', 'AM'), ('3', '12', 'PM'),
...: ('4', '10', 'PM')]
In [40]: def key(t):
...: h, m, z = t
...: return z, int(h)%12, int(m)
...:
In [41]: max(timeList,key=key)
Out[41]: ('8', '23', 'PM')
But what would make the most sense is to actually use datetime.time objects, instead of pretending a tuple of strings is a good way to store time.
So something like:
In [49]: def to_time(t):
...: h, m, z = t
...: h, m = int(h)%12, int(m)
...: if z == "PM":
...: h += 12
...: return datetime.time(h, m)
...:
In [50]: real_time_list = list(map(to_time, timeList))
In [51]: real_time_list
Out[51]:
[datetime.time(16, 12),
datetime.time(20, 23),
datetime.time(4, 3),
datetime.time(1, 34),
datetime.time(12, 48),
datetime.time(4, 13),
datetime.time(11, 9),
datetime.time(15, 12),
datetime.time(16, 10)]
In [52]: list(map(str, real_time_list))
Out[52]:
['16:12:00',
'20:23:00',
'04:03:00',
'01:34:00',
'12:48:00',
'04:13:00',
'11:09:00',
'15:12:00',
'16:10:00']
Note, now max “just works”:
In [54]: t = max(real_time_list)
In [55]: print(t)
20:23:00
And if you need a pretty string to print, just do the formatting at that point:
In [56]: print(t.strftime("%I:%M %p"))
08:23 PM