2

I have a list like this:

[('100701260', '10:23:15'),
   ('100701260', '07:52:27'),
   ('100700853', '09:26:52')]

Is it possible to sort it by time like this:

[('100701260', '07:52:27'),
('100700853', '09:26:52'),
('100701260', '10:23:15')]

I know it is possible to sort by date when we have a list. But I am not sure about a list of tuples.

accdias
  • 5,160
  • 3
  • 19
  • 31
Mohammad
  • 55
  • 4

2 Answers2

3

Using itemgetter:

>>> t = [('100701260', '10:23:15'),
...      ('100701260', '07:52:27'),
...      ('100700853', '09:26:52')]
>>> from operator import itemgetter
>>> sorted(t, key=itemgetter(1))
[('100701260', '07:52:27'),
 ('100700853', '09:26:52'),
 ('100701260', '10:23:15')]

Strings in %H:%M:%S format will already sort chronologically by default, so there's no need to convert into time instances (unless you want the extra data validation and don't mind the runtime slowdown).

Take care: if your time strings are not all serialized the same way, e.g. you had the possibility of a "9:26:52" instead of the "09:26:52" here, then sorting directly as strings will not be reliable.

wim
  • 338,267
  • 99
  • 616
  • 750
  • Actually, that's not always true, since we can have strings like `10:23:45` and `9:45:60`, for example, which are still valid `%H:%M:%S` but they will not sort correctly if considered just as strings. – accdias Jan 24 '23 at 15:34
  • 1
    @accdias Hmm, I can not parse `9:45:60` with "%H:%M:%S" (second must be in 0..59) but indeed the leading zero does seem to be optional. Strange, because it always serialises with leading zeros when using strftime for the same format. – wim Jan 24 '23 at 18:52
  • 1
    Yes, for strptime, it's [documented](https://docs.python.org/3/library/datetime.html#strftime-and-strptime-behavior) to be optional (see note 9). – Kelly Bundy Jan 24 '23 at 19:37
  • That `60` was a typo. Sorry for that. I was referring to the leading zero. But it me leads to think about leap seconds also. Is it able to parse `23:59:60`, for example? – accdias Jan 25 '23 at 00:27
  • Just tested here, and it works for `23:59:60` and `23:59:61`, as it should. :-) – accdias Jan 25 '23 at 00:32
2

You can use time.strptime() for that:

import time

t = [
    ('100701260', '10:23:15'),
    ('100701260', '07:52:27'),
    ('100700853', '09:26:52')
]

t.sort(key=lambda(x: time.strptime(x[1], '%H:%M:%S'))

The snippet above will leave t with:

[('100701260', '07:52:27'), ('100700853', '09:26:52'), ('100701260', '10:23:15')]

And constructing on top of @wim's answer, you can do it without any import:

t = [
    ('100701260', '10:23:15'),
    ('100701260', '07:52:27'),
    ('100700853', '09:26:52')
]

t.sort(key=lambda x: x[1])
accdias
  • 5,160
  • 3
  • 19
  • 31