Reputation: 636
I have a list of durations like below
['5d', '20h', '1h', '7m', '14d', '1m']
where d
stands for days, h
stands for hours and m
stands for minutes.
I want to get the highest duration from this list(14d
in this case). How can I get that from this list of strings?
Upvotes: 9
Views: 399
Reputation: 36584
np.argmax
on pd.to_timedelta
:
import numpy as np
import pandas as pd
durations = ['5d', '20h', '1h', '7m', '14d', '1m']
durations[np.argmax(pd.to_timedelta(durations))]
Out[24]: '14d'
pd.to_timedelta
turns a string into a duration (source), and np.argmax
returns the index of the highest element.
Upvotes: 15
Reputation: 2036
here is a solution with regular expression
import numpy as np
import re
new_list = []
x=['5d', '20h', '1h', '7m', '14d', '1m']
map_time={"d":1440, "h":60, "m":1}
for item in x:
letter=re.findall("[a-zA-Z]+",item)
number=re.findall("[1-9]+",item)
new_list.append(map_time[letter[0]]*int(number[0]))
x[np.argmax(new_list)]
Upvotes: 3
Reputation: 50076
Provided that your times are well-formed, you can find the max
based on a single regular expression:
>>> import re
>>>
>>> durations = ['5d', '20h', '1h', '7m', '14d', '1m']
>>> pattern = re.compile(r'(?:(\d*)d)?(?:(\d*)h)?(?:(\d*)m)?')
>>> max(inp, key=lambda tme: tuple(map(int, pattern.match(tme).groups(default=0))))
'14d'
The regular expression creates a tuple of days, hours, minutes as strings. The tuple(map(int, ...))
converts it to integers. max
picks the largest of these tuples, which naturally weight days stronger than hours stringer than minutes.
Upvotes: 2
Reputation: 3612
Pure python solution. We could store mapping between our time extensions (m
, h
, d
) and minutes (here time_map
), to find highest duration. Here we're using max()
with key
argument to apply our mapping.
inp = ['5d', '20h', '1h', '7m', '14d', '1m']
time_map = {'m': 1, 'h': 60, 'd': 24*60}
print(max(inp, key=lambda x:int(x[:-1])*time_map[x[-1]])) # -> 14d
Upvotes: 13
Reputation: 1256
One possible way :
duration = ['5d', '20h', '1h', '7m', '14d', '1m', '2d']
duration_std = [0]*len(duration)
equivalence = {"d":60*60*24, "h":60*60, "m":60}
for idx, val in enumerate(duration):
duration_std[idx] = int(val[:-1])*equivalence[val[-1]]
print(duration[duration_std.index(max(duration_std))])
Output
"14d"
Upvotes: 1
Reputation: 51037
Here's an absolute hack which solves the problem in a bad but clever way: Python's min
and max
functions can be used with a key
function which is used to compare elements, so that it returns the element minimising or maximising that function. If the key
function returns a tuple, then the order is determined by the first component of the tuple, using the second component as a tie-breaker.
We can exploit the fact that the last characters 'd'
, 'h'
and 'm'
can be compared in alphabetical order; a day is longer than an hour is longer than a minute. This means the longest duration has the minimum character in alphabetical order, with the maximum integer as a tie-breaker. Maximising that integer is the same as minimising its negation:
>>> durations = ['5d', '20h', '1h', '7m', '14d', '1m']
>>> min(durations, key=lambda d: (d[-1], -int(d[:-1])))
'14d'
Upvotes: 5
Reputation: 13858
lst = ['5d', '20h', '1h', '7m', '14d', '1m']
max(lst, key=lambda s: (-ord(s[-1]), int(s[:-1])))
Output:
'14d'
Useful for this particular set of strings, but if the format differs, will need to adjust the first element of the tuple accordingly. Right now it makes sense because s
> m
> h
> d
.
Upvotes: 3