0

Below is the data which I have in a list. 'm' being minutes and 'h' being hours, I need to sort this from shortest to longest with Python.

10m
10m
10m
11h59m
11m
12m
13h24m
13m
13m
13m
14m
14m
15m
17m
17m
1h01m
1h05m
1h05m
1h11m
1h15m
1h19m
1h25m
1h30m
1h31m
1h41m
1h46m
1h50m
1h54m
1m
20m
21m
22m
22m
22m
24m
25m
28m
28m
28m
29m
2h00m
2h07m
2h24m
2h27m
2h35m
2h51m
2h51m
2m
2m
2m
2m
2m
2m
2m
30m
31m
31m
31m
32m
32m
34m
35m
37m
3h18m
3h24m
3h28m
3h31m
3h43m
3h45m
3h53m
3m
3m
3m
40m
44m
4h11m
4h25m
4h43m
4h45m
4h57m
4m
4m
4m
4m
51m
51m
55m
58m
5h29m
5h39m
5h40m
6h06m
6h13m
6h20m
6m
7h16m
7h36m
7h43m
7m
8h50m
8m
8m
8m
8m
9h39m
9m
9m
9m
9m
9m
9m
artemis
  • 6,857
  • 11
  • 46
  • 99
Frankie
  • 79
  • 5
  • Yes, create function which converts the string to a number and then sort by that number. – zvone Nov 11 '19 at 16:10
  • You should probably start by writing a parser to convert the total time into a sortable integer-like object (probably as total minutes), as opposed to performing a lexicographical sort. Then you can use the `sort` function in Python do accomplish this pretty easily. Maybe go with a dictionary whose key is the input as a string and value is the total time in minutes. – h0r53 Nov 11 '19 at 16:11
  • @CaitLANJenner: Actually, [`sorted`](https://docs.python.org/3/library/functions.html#sorted) takes `key` argument which can handle that. There is no need for a dictionary. – zvone Nov 11 '19 at 16:12

2 Answers2

4

You could use a dictionary to map symbols to durations in minutes or seconds, whatever will be your smallest unit, and then use a regular expression to extract the parts of the duration and get their sum.

>>> import re
>>> d = {"s": 1, "m": 60, "h": 3600}
>>> def seconds(line):
...    return sum(int(n) * d[u] for n, u in re.findall("(\d+)(\w)", line))
...
>>> seconds("8h50m")
31800

Then use that function as a key to sorted:

>>> sorted(lst, key=seconds)
['2m', '2m', '2m', ..., '7h43m', '8h50m', '9h39m']
tobias_k
  • 81,265
  • 12
  • 120
  • 179
  • You can, or course, also use a "proper" time parsing function, e.g. `strptime`, but I found it difficult to use those [with "optional bits"](https://stackoverflow.com/q/30584364/1639625). – tobias_k Nov 11 '19 at 16:47
0

Here is another way to achieve your goal.

New version:

def conversion(t):
    """ convert time to minutes """
    if 'h' in t:
        hours = int(t.split('h')[0])
        minutes = int(t.split('h')[1].split('m')[0])
        minutes = hours * 60 + minutes
    else:
        minutes = int(t.split('m')[0])

    return minutes

if __name__ == "__main__":
    values = ['10m', '10m', '10m', '11h59m', '11m', '12m', '13h24m', '13m', '13m', '13m', '14m', '14m', '15m', '17m', '17m', '1h01m', '1h05m', '1h05m', '1h11m', '1h15m', '1h19m', '1h25m', '1h30m', '1h31m', '1h41m', '1h46m', '1h50m', '1h54m', '1m', '20m', '21m', '22m', '22m', '22m', '24m', '25m', '28m', '28m', '28m', '29m', '2h00m', '2h07m', '2h24m', '2h27m', '2h35m', '2h51m', '2h51m', '2m', '2m', '2m', '2m', '2m', '2m', '2m', '30m', '31m', '31m', '31m', '32m', '32m', '34m', '35m', '37m', '3h18m', '3h24m', '3h28m', '3h31m', '3h43m', '3h45m', '3h53m', '3m', '3m', '3m', '40m', '44m', '4h11m', '4h25m', '4h43m', '4h45m', '4h57m', '4m', '4m', '4m', '4m', '51m', '51m', '55m', '58m', '5h29m', '5h39m', '5h40m', '6h06m', '6h13m', '6h20m', '6m', '7h16m', '7h36m', '7h43m', '7m', '8h50m', '8m', '8m', '8m', '8m', '9h39m', '9m', '9m', '9m', '9m', '9m', '9m']
    print(sorted(values, key=conversion))

Output:

['1m', '2m', '2m', '2m', '2m', '2m', '2m', '2m', '3m', '3m', '3m', '4m', '4m', '4m', '4m', '6m', '7m', '8m', '8m', '8m', '8m', '9m', '9m', '9m', '9m', '9m', '9m', '10m', '10m', '10m', '11m', '12m', '13m', '13m', '13m', '14m', '14m', '15m', '17m', '17m', '20m', '21m', '22m', '22m', '22m', '24m', '25m', '28m', '28m', '28m', '29m', '30m', '31m', '31m', '31m', '32m', '32m', '34m', '35m', '37m', '40m', '44m', '51m', '51m', '55m', '58m', '1h01m', '1h05m', '1h05m', '1h11m', '1h15m', '1h19m', '1h25m', '1h30m', '1h31m', '1h41m', '1h46m', '1h50m', '1h54m', '2h00m', '2h07m', '2h24m', '2h27m', '2h35m', '2h51m', '2h51m', '3h18m', '3h24m', '3h28m', '3h31m', '3h43m', '3h45m', '3h53m', '4h11m', '4h25m', '4h43m', '4h45m', '4h57m', '5h29m', '5h39m', '5h40m', '6h06m', '6h13m', '6h20m', '7h16m', '7h36m', '7h43m', '8h50m', '9h39m', '11h59m', '13h24m']

OLD VERSION of the Code

def conversion(t):
    """ convert time to minutes """
    if 'h' in t:
        hours = int(t.split('h')[0])
        minutes = int(t.split('h')[1].split('m')[0])
        minutes = hours * 60 + minutes
    else:
        minutes = int(t.split('m')[0])

    return minutes

def back_conversion(minutes):
    """ convert minutes to time """
    if minutes >= 60:
        hours = minutes // 60
        newminutes = minutes % 60
        if newminutes == 0:
            result = '{}h'.format(hours)
        else:
            result = '{}h{}m'.format(hours, newminutes)
    else:
        result = '{}m'.format(minutes)

    return result


if __name__ == "__main__":
    values = ['10m', '10m', '10m', '11h59m', '11m', '12m', '13h24m', '13m', '13m', '13m', '14m', '14m', '15m', '17m', '17m', '1h01m', '1h05m', '1h05m', '1h11m', '1h15m', '1h19m', '1h25m', '1h30m', '1h31m', '1h41m', '1h46m', '1h50m', '1h54m', '1m', '20m', '21m', '22m', '22m', '22m', '24m', '25m', '28m', '28m', '28m', '29m', '2h00m', '2h07m', '2h24m', '2h27m', '2h35m', '2h51m', '2h51m', '2m', '2m', '2m', '2m', '2m', '2m', '2m', '30m', '31m', '31m', '31m', '32m', '32m', '34m', '35m', '37m', '3h18m', '3h24m', '3h28m', '3h31m', '3h43m', '3h45m', '3h53m', '3m', '3m', '3m', '40m', '44m', '4h11m', '4h25m', '4h43m', '4h45m', '4h57m', '4m', '4m', '4m', '4m', '51m', '51m', '55m', '58m', '5h29m', '5h39m', '5h40m', '6h06m', '6h13m', '6h20m', '6m', '7h16m', '7h36m', '7h43m', '7m', '8h50m', '8m', '8m', '8m', '8m', '9h39m', '9m', '9m', '9m', '9m', '9m', '9m']
    sorted_values  = sorted([conversion(v) for v in values])
    final_results = [back_conversion(v) for v in sorted_values]
    print(final_results)

Outputs

['1m', '2m', '2m', '2m', '2m', '2m', '2m', '2m', '3m', '3m', '3m', '4m', '4m', '4m', '4m', '6m', '7m', '8m', '8m', '8m', '8m', '9m', '9m', '9m', '9m', '9m', '9m', '10m', '10m', '10m', '11m', '12m', '13m', '13m', '13m', '14m', '14m', '15m', '17m', '17m', '20m', '21m', '22m', '22m', '22m', '24m', '25m', '28m', '28m', '28m', '29m', '30m', '31m', '31m', '31m', '32m', '32m', '34m', '35m', '37m', '40m', '44m', '51m', '51m', '55m', '58m', '1h1m', '1h5m', '1h5m', '1h11m', '1h15m', '1h19m', '1h25m', '1h30m', '1h31m', '1h41m', '1h46m', '1h50m', '1h54m', '2h', '2h7m', '2h24m', '2h27m', '2h35m', '2h51m', '2h51m', '3h18m', '3h24m', '3h28m', '3h31m', '3h43m', '3h45m', '3h53m', '4h11m', '4h25m', '4h43m', '4h45m', '4h57m', '5h29m', '5h39m', '5h40m', '6h6m', '6h13m', '6h20m', '7h16m', '7h36m', '7h43m', '8h50m', '9h39m', '11h59m', '13h24m']
codrelphi
  • 1,075
  • 1
  • 7
  • 13