获取时间段的值

时间:2015-09-28 16:02:35

标签: python algorithm datetime python-3.x

我在Python3中编写程序,我需要的其中一个函数是通过引用两个日期时间值来计算一个值,如下所示。

想象一下,这一天分为8个三小时的块,总是从0000 UTC开始。这些块中的每一个都将具有值x,该值将从块到块变化,但在块本身内不会变化。

我需要将函数传递给一个起始日期时间对象和一个结束日期时间对象,并且该函数返回一个值,该值是x的乘积,以及该起始日期时间对象和结束日期时间对象之间该块中的分钟数

因此,例如,如果开始时间是0100 UTC并且结束时间是0200 UTC并且0000 UTC到0300 UTC块的x值是20那么这很容易,值为60 * 20 = 1200。 / p>

如果开始时间是0100 UTC并且结束时间是0400 UTC并且0000 UTC到0300 UTC块的x值是20并且0300 UTC到0600 UTC块的x值是30,那么总和将是是(20 * 120)+(60 * 30)= 4200

开始时间和结束时间可能跨越多个块甚至多天。

我建议做的是建立一个" day_list"每个字典的字典是{" startchunk_time":#(例如0000 UTC)," endchunk_time":#(例如0300 UTC)," x":value} 。然后伪代码将是:

def find_value(start_time, end_time):
    test_time = start_time
    while test_time < end_time:
        for item in day_list:
            if test_time > itemstartchunk_time and test_time < endchunk_time:
                #code to add the current x value and increase the test_time by one minute

因此,这涉及遍历整个&#34; day_list&#34;每次,即使已找到相关值,下一个通常也在同一块中。

我的问题是:(i)有一种方法可以在找到值后突破for循环; (ii)是否有更有效的方式来做到这一点?

2 个答案:

答案 0 :(得分:0)

您的任务主要是为[a, b]区间找到分段常数函数f(t)的定积分。因此,相应的不定积分F(t)是具有相同转变点的分段线性函数。来自calculus

$$\int_a^b f(t) \,dt = F(b) - F(a)$$

让我们t[i]i件的开始时间(转换点),f[i]为相应的值。要查找给定时间段的累计值,您只需要找到F(a)F(b)。您可以提前计算的转换点中的F[i]值。因此,如果i已知,则操作时间为O(1)

如果t[i]次排序,那么您可以使用二进制搜索(i模块)在s时间内找到O(log n)任意给定输入时间bisect 。如果所有广告位的持续时间相同,例如3小时,那么您可以通过分析找到i(在O(1)时间内):

assert s >= t[0]
i = (s - t[0]) // timedelta(hours=3)

假设:

  • 同一时段的值,例如03..06可能在不同日期不同
  • 输入时间段(例如[a, b))未被排序且它们不是等间隔的。

这是在常量时间内计算find_value()的代码示例:

#!/usr/bin/env python3
from datetime import datetime, timedelta

slot_size = timedelta(hours=3)
slot_size_minutes = slot_size // timedelta(minutes=1)
f = [20, 30] # x values from the question
min_time = datetime(2015, 9, 29) # the time corresponding to f[0]
max_time = min_time + slot_size * len(f)

# compute F[i]
F = [0] * (len(f) + 1)
for i in range(len(f)):
    F[i+1] = F[i] + slot_size_minutes * f[i]

def find_value(start_time, end_time):
    return indefinite_integral(end_time) - indefinite_integral(start_time)

def indefinite_integral(t):
    if min_time <= t <= max_time:
        i = (t - min_time) // slot_size
        t_i = min_time + i * slot_size # i-th transition point
        minutes_in_ith_slot = (t - t_i) // timedelta(minutes=1)  # complete minutes
        return F[i] + f[i] * minutes_in_ith_slot if i < len(f) else F[i]
    else:
        raise ValueError('%r is not in [%s, %s] time range' % (
                         t, min_time, max_time))

使用示例:

def tt(hhmm):
    hour, minute = divmod(int(hhmm), 100)
    return min_time.replace(hour=hour, minute=minute)

assert find_value(tt("0100"), tt("0200")) == 1200
assert find_value(tt("0100"), tt("0400")) == 4200

答案 1 :(得分:-1)

绝对有办法做到这一点!如果有遗嘱有办法;)毕竟你使用的是Python。 For循环只是条件语句(即。ifelifelse),因此添加else语句(仅当循环正常终止时才执行“else”) )。以下是该做什么的示例:

ctr = 1
while True:
    print "CTR: {0}".format(ctr)
    for x in xrange(10):
        print '\t{0}'.format(x)
        if x == 5:
            print "break FOR loop"
            break
    else:
        print "The FOR loop has completed and no break was hit."
        # do something when a breakpoint hasn't been hit
        break       # break WHILE loop

    print "Break was hit in the FOR loop. Kill the WHILE loop"
    # do something when the FOR loop breaks
    break       # break WHILE loop

这可能有点令人困惑,但它应该运行并让您知道该怎么做。按原样运行,然后尝试注释:

if x == 5:
    print "break FOR loop"
    break

再次运行代码,看看会发生什么。祝你好运