2015-03-31 51 views
12

以數字形式給出一個月份(例如,2月份爲2),您如何找到其各個季度的第一個月份(例如,1月份爲1)?Python中給定月份的第一個月

我通過datetime模塊文檔和他們的日期時間函數的熊貓文檔閱讀,這應該是相關的,但我找不到解決此問題的函數。

從本質上講,我想了解的是我怎麼能產生像一個低於一個函數,給定月份X,輸出與X的季度第一個月的數量。

>> first_month_quarter(5) 
4 
+7

不公平的,這將是在未來類似的問題有用的人。我希望在嘗試解決這個問題時我可以自己找到答案。對於自我回答,SO政策很好:http://stackoverflow.com/help/self-answer。 – 2015-03-31 18:34:38

+1

你認爲有多少人會有「類似的問題」*,但無法自己解決這個問題?此外,這並不公平 - 這不是針對任何**的代碼編寫服務。 SO政策沒問題,對主題問題**有很好的答案**,這並不意味着您可以發佈任何您想要的內容。 – jonrsharpe 2015-03-31 18:36:20

+0

@jonrsharpe:OP也是第一個回答者。 – unutbu 2015-03-31 18:36:35

回答

19

這是一個簡單的繪圖功能,需要轉換:

1 2 3 4 5 6 7 8 9 10 11 12 
      | 
      V 
1 1 1 4 4 4 7 7 7 10 10 10 

這可以在許多完成用積分計算的方法S,其中兩個是:

def firstMonthInQuarter(month): 
    return (month - 1) // 3 * 3 + 1 

和:

def firstMonthInQuarter(month): 
    return month - (month - 1) % 3 

首先涉及到一個月的整數除法轉換爲一個從零開始的一個月拿到從零開始季度,乘法把這一回到基於零的月份(但是本月的開始),然後再次添加一個以使範圍爲1..12

month -1 //3 *3 +1 
----- -- --- -- -- 
    1 0 0 0 1 
    2 1 0 0 1 
    3 2 0 0 1 
    4 3 1 3 4 
    5 4 1 3 4 
    6 5 1 3 4 
    7 6 2 6 7 
    8 7 2 6 7 
    9 8 2 6 7 
    10 9 3 9 10 
    11 10 3 9 10 
    12 11 3 9 10 

第二隻減去四分之一內的位置(0,1,2)從月本身,以獲得開始的月份。

month(a) -1 %3(b) a-b 
-------- -- ----- --- 
     1 0  0 1 
     2 1  1 1 
     3 2  2 1 
     4 3  0 4 
     5 4  1 4 
     6 5  2 4 
     7 6  0 7 
     8 7  1 7 
     9 8  2 7 
     10 9  0 10 
     11 10  1 10 
     12 11  2 10 
10

這是TigerhawkT3建議的答案。也許迄今爲止最尖銳的建議,顯然也是最快的。

import math 

def first_month_quarter(month): 
    return int(math.ceil(month/3.)) * 3 - 2 

例如:

>> first_month_quarter(5) 
4 
+2

標準的'math'模塊也有一個'ceil'功能,在功能上等同於此。 – TigerhawkT3 2015-03-31 18:42:16

+0

好點!我從來沒有真正知道如何選擇'numpy'和'math'的'ceil'函數。不知道他們的效率和產量如何/何時不同。 – 2015-03-31 18:44:25

+1

您也可以使用'((月 - 1)// 3%4)* 3 + 1',它在1和12之間的月份(含)之間一致,並且總是返回月1,4,7或1月中的一個10'爲'months'小於1或大於12. – unutbu 2015-03-31 18:49:11

13
def first_month(month): 
    return (month-1)//3*3+1 

for i in range(1,13): 
    print i, first_month(i) 
+0

這就是我的答案,因爲在問及時我沒有睡着:-)轉換爲基於零的月份數並只使用整數數學。 – paxdiablo 2015-04-01 01:32:36

20

這不是那麼漂亮,但如果速度是很重要的一個簡單的列表查找屠殺math

def quarter(month, quarters=[None, 1, 1, 1, 4, 4, 4, 
          7, 7, 7, 10, 10, 10]): 
    """Return the first month of the quarter for a given month.""" 
    return quarters[month] 

一個timeit比較表明,這是大概是TigerhawkT3的數學方法的兩倍。


測試腳本:

import math 

def quarter(month, quarters=[None, 1, 1, 1, 4, 4, 4, 
          7, 7, 7, 10, 10, 10]): 
    """Return the first month of the quarter for a given month.""" 
    return quarters[month] 

def firstMonthInQuarter1(month): 
    return (month - 1) // 3 * 3 + 1 

def firstMonthInQuarter2(month): 
    return month - (month - 1) % 3 

def first_month_quarter(month): 
    return int(math.ceil(month/3.)) * 3 - 2 

if __name__ == '__main__': 
    from timeit import timeit 
    methods = ['quarter', 'firstMonthInQuarter1', 'firstMonthInQuarter2', 
       'first_month_quarter'] 
    setup = 'from __main__ import {}'.format(','.join(methods)) 
    results = {method: timeit('[{}(x) for x in range(1, 13)]'.format(method), 
           setup=setup) 
       for method in methods} 
    for method in methods: 
     print '{}:\t{}'.format(method, results[method]) 

結果:

quarter: 3.01457574242 
firstMonthInQuarter1: 4.51578357209 
firstMonthInQuarter2: 4.01768559763 
first_month_quarter: 8.08281871176 
+9

當答案稍後出現時,提出速度聲明總是有風險的。對於千萬次迭代,你的方法需要7.2秒,但我的答案中的兩個是7.0和7.3。事實上,即使是數學的一個時鐘在7.6,所以它不是那麼糟糕。不是說你的解決方案不好(實際上這個地段之間幾乎沒有什麼區別),只是說你可能想回復一些關於索賠的問題:-)無論如何,謝謝你對'timeit'的教育,我會沒見過之前 – paxdiablo 2015-04-02 13:40:33

+0

@paxdiablo真的!然而,我只是重新運行了測試,包括你的方法,並且看到了類似的結果 - 使用列表的速度是「math.ceil」的兩倍以上,比整數運算速度快25-50%('timeit'默認爲1,000,000次迭代)。我已經用我的測試和結果更新了答案。 – jonrsharpe 2015-04-02 14:15:05

2

包裝查找錶轉換爲64位的文字:

def firstMonthOfQuarter(month): 
    return (0x000aaa7774441110L >> (month << 2)) & 15 
相關問題