8

I have a list with these items:

hours = ['19:30', '20:10', '20:30', '21:00', '22:00']

Assuming that now it's 20:18, how can I get the '20:10' item from list? I want to use this to find the current running show in a TV Guide.

Katriel
  • 120,462
  • 19
  • 136
  • 170
ov1d1u
  • 958
  • 1
  • 17
  • 38

6 Answers6

10
>>> import datetime
>>> hours = ['19:30', '20:10', '20:30', '21:00', '22:00']
>>> now = datetime.datetime.strptime("20:18", "%H:%M")
>>> min(hours, key=lambda t: abs(now - datetime.datetime.strptime(t, "%H:%M")))
'20:10'
Katriel
  • 120,462
  • 19
  • 136
  • 170
  • 2
    +1 for doing what the OP has asked for (finding the closest hour), but he also wrote that he wants to find the "current running show" - so for `20:22` you get `20:30` which obviously isn't the currently running show. – Tim Pietzcker Nov 07 '10 at 16:59
6

easy but dirty way

max(t for t in sorted(hours) if t<=now)
Kabie
  • 10,489
  • 1
  • 38
  • 45
2

I'm not a Python programmer, but I'd use the following algorithm:

  1. Convert everything to "minutes after midnight", e.g. hours = [1170 (= 19*60+30), 1210, ...], currenttime = 1218 (= 20*60+18).

  2. Then just loop thorugh hours and find the last entry which is smaller than currenttime.

Heinzi
  • 167,459
  • 57
  • 363
  • 519
  • +1: This would actually address the problem of the "currently running show". Perhaps it might be necessary to sort the times first. – Tim Pietzcker Nov 07 '10 at 17:24
1

You can use functions in the time module; time.strptime() allows you to parse a string into a time-tuple, then time.mktime() converts this to seconds. You can then simply compare all items in seconds, and find the smallest difference.

Oliver Charlesworth
  • 267,707
  • 33
  • 569
  • 680
1
import bisect
# you can use the time module like katrielalex answer which a standard library 
# in python, but sadly for me i become an addict to dateutil :)
from dateutil import parser 

hour_to_get = parser.parse('20:18')

hours = ['19:30', '20:10', '20:30', '21:00', '22:00']
hours = map(parser.parse, hours) # Convert to datetime.

hours.sort() # In case the list of hours isn't sorted.

index = bisect.bisect(hours, hour_to_get)

if index in (0, len(hours) - 1):
    print "there is no show running at the moment"
else:
    print "running show started at %s " % hours[index-1] 

Hope this can help you :)

mouad
  • 67,571
  • 18
  • 114
  • 106
  • 2
    This assumes that times with one-digit hours or minutes are represented with a leading zeros for the respective values. – Björn Pollex Nov 07 '10 at 16:17
  • he can convert them from the beginning before calling bisect.bisect – mouad Nov 07 '10 at 16:19
  • bisect works if the list is sorted. Consider `hours = ['19:30', '20:10', '20:30', '23:00', '21:00', '22:00']` – khachik Nov 07 '10 at 16:20
  • @singularity: True, but that should be part of your answer because, as your answer stands now, it is incorrect. – Björn Pollex Nov 07 '10 at 16:22
  • 3
    -1 This is elegant until you think about all the ways it can go wrong, not to mention that you are basically re-implementing `min`. Once you've padded all the times, sorted them, parsed the two adjacent elements of the list into times, and found their minimum, the elegance goes away. – Katriel Nov 07 '10 at 16:25
  • @Space_C0wb0y: are we having an exam or what ??? i know that i'm just given indication to the OP and i think he can continue from there – mouad Nov 07 '10 at 16:30
  • @katrielalex: don't rush and put a -1 Check out the timeit. – mouad Nov 07 '10 at 16:38
  • 2
    @singularity: I think my vote stil stands: your answer, especially now that you have added all the extra cruft, is Not The Right Way To Do This. Especially since you now require `dateutil`, which isn't standard with Python. If an extra 20 nanoseconds matters, the OP shouldn't be using Python anyway. – Katriel Nov 07 '10 at 16:42
  • @katrielalex : heheheh are we playing in code Golf ???? now you have just demonstrate to me that most people here don't understand what a good or bad code, less line code don't mean that it's good , but well i don't care about your down vote just learn how to read code that's all – mouad Nov 07 '10 at 16:48
  • 1
    @singularity: From your profile I have learned that you think most people on StackOverflow are jerks. I suspect that their reaction to you might have something to do with the way you formulate your comments which do come across as rather aggressive. At least that's my impression. @Space_C0wb0y and @katrielalex have written honest, correct, and fair critiques of your answer, and you get back at them with a vengeance. Think about it. – Tim Pietzcker Nov 07 '10 at 17:14
  • @Tim Pietzcker : what vengeance ? if you have read my profile you will find out that i have never put any -1 at all (this will be vengeance), specially when some people put -1 without putting any comment of what wrong; and why in the first we put -1 ? have you think about it? i think that -1 should be put to wrong answers not for answer that we don' like, and have you see all my comment and answer or you have just see this one and you think that you can judge me ? and in fact i don't have anything again there comment i dislike people that are here in competition and not for helping others – mouad Nov 07 '10 at 17:23
  • 1
    @singularity: I find injections like "are we having an exam or what ???" or "heheheh are we playing in code Golf ????" childish and petulant and able to distract people from the merits of your answer and focus them on your behaviour. But in this concrete case, katrielalex explained *why* he downvoted. Twice. And he's right. Your answer is not that good. – Tim Pietzcker Nov 07 '10 at 17:28
  • 1
    @Tim Pietzcker: yes you're right , maybe i want to take my anger over them (for people that put -1 without a comment and they are mostly wrong not just in my case) and despite i still mostly believe in what i wrote in my comment and my answer is good maybe not good as the most voted (doing n - operator , doing a min() O(n) ) and in my case (a Trim sort nlog(n) , bisect log(n) ) but if we look at the number of line (code golf) yes sure his answer will "won" (competition right :) ) . but thank you for opening my eyes i never should did what i did, and again sorry for taking your time ; – mouad Nov 07 '10 at 17:46
  • @katrielalex, @Space_C0wb0y: i want to apologize for my last behavior please accept my apologies, and sorry if i offend you in any way ; – mouad Nov 07 '10 at 17:48
  • Ok, a problem here... If the hour list is: hours = ['19:00', '20:45', '21:45', '22:45', '01:30'] it returns '20:45' when the given hour is 20:30, for example... – ov1d1u Nov 07 '10 at 18:30
  • @ov1d1u: __hours = ['19:00', '20:45', '21:45', '22:45', '01:30'] it returns '20:45' when the given hour is 20:30__ excuse me but it's not the closet hour ??? what should it return ??? – mouad Nov 07 '10 at 18:46
  • @singularity: it should return 19:00, as I said that "I want to use this to find the current running show in a TV Guide." So, the current show in this case is the one started at 19:00 :) – ov1d1u Nov 07 '10 at 20:10
  • @ov1d1u: ahhh ok now i understand i will update my answer sorry if i didn't get it the first time. – mouad Nov 07 '10 at 20:44
  • +1: This is a good answer because it identifies the best way to search a sorted list - the bisect module. The assumption of leading zeros and a sorted list are fair given the lack of detail in the original question. The question had 24-hour times and a sorted list. @singularity - I suggest you roll back your code to the original version, and simply add those assumptions. It *was* an elegant and useful answer. – camh Nov 08 '10 at 12:37
1

@katrielalex & Tim

import itertools
[x for x in itertools.takewhile( lambda t: now > datetime.datetime.strptime(t, "%H:%M"), hours )][-1]
Ante
  • 5,350
  • 6
  • 23
  • 46