首先上題目钻洒,題目思路很簡單,乍看一下也是很好解決锄开,但是在解題的過程中還是遇到不少坑素标,Python雖然輪子多,但是坑也不少萍悴。
這里簡單反思一下解題過程中头遭,遇到的各種各樣的坑。
The bill is represented as an array with information about the calls. Help Nicola to calculate the cost for each of Sophia calls. Each call is represented as a string with date, time and duration of the call in seconds in the follow format:
"YYYY-MM-DD hh:mm:ss duration"
The date and time in this information are the start of the call.
Space-Time Communications Co. has several rules on how to calculate the cost of calls:
First 100 (one hundred) minutes in one day are priced at 1 coin per minute;
After 100 minutes in one day, each minute costs 2 coins per minute;
All calls are rounded up to the nearest minute. For example 59 sec ≈ 1 min, 61 sec ≈ 2 min;
Calls count on the day when they began. For example if a call was started 2014-01-01 23:59:59, then it counted to 2014-01-01;
For example:
2014-01-01 01:12:13 181
2014-01-02 20:11:10 600
2014-01-03 01:12:13 6009
2014-01-03 12:13:55 200
First day -- 181s≈4m -- 4 coins;
Second day -- 600s=10m -- 10 coins;
Third day -- 6009s≈101m + 200s≈4m -- 100 + 5 * 2 = 110 coins;
Total -- 124 coins.
Input: Information about calls as a tuple of strings.
Output: The total cost as an integer.
具體題目可以參見鏈接https://py.checkio.org/zh-hans/mission/calls-home/
最常規(guī)的解法
首先癣诱,我們獲取日期信息和通話時間计维,再將相同日期的通話時間進(jìn)行累加。最簡單的想法是利用字典的鍵位的唯一性撕予,
每取到一個日期的值鲫惶,就將對應(yīng)字典的value更新即可。但是這里有一個問題:
- 如果字典key存在那么实抡,使用直接賦值和增量賦值(+=)都是沒有問題的欠母。
- 如果字典key不存在欢策,那么使用直接賦值是可行的,但是使用增量賦值就會報keyerror
此處插入一段:
In line with the fail-fast philosophy, dict access with d[k] raises an error when k is not an existing key. Every Pythonista
knows that d.get(k, default) is an alternative to d[k] whenever a default value is more convenient than handling KeyError.
那么如果使字典也能實現(xiàn)不存在key值的時候進(jìn)行增量賦值呢赏淌,這里可以使用dict.get(value,default=None)方法來實現(xiàn)踩寇,
該方法返回指定鍵的值,如果值不在字典中返回default值六水。由此可以得到以下第一種解法
from math import ceil
def total_cost(calls):
dict = {}
for call in calls:
date, _, length = call.split(" ")
dict[date] = dict.get(date,0) + ceil(int(length)/60)
return sum([i*2-100 if i>100 else i for i in dict.values()])
使用Built-in函數(shù)Counter()的解法
Counter()是collections下面的一個計數(shù)器函數(shù)俺孙。有興趣的可以去看看Counter()的源碼,Counter()繼承dict類缩擂,因此我們可以使用dict的方法來使用counter().因為 Counter 實現(xiàn)了defaultdict()的__missing__ 方法鼠冕, 所以當(dāng)訪問不存在的key的時候,返回值為0胯盯。利用這個特性懈费,我們就可以無憂慮的使用增量賦值來達(dá)成我們的目的。
from math import ceil
from collections import Counter
def total_cost(calls):
dict_total = Counter()
for call in calls:
date, _, length = call.split(" ")
dict_total[date] += ceil(int(length)/60)
return return sum([i*2-100 if i>100 else i for i in dict_total.values()])
當(dāng)然你也可以使用counter().update方法博脑,把所有的值放在一個可迭代對象中憎乙,然后傳入update()函數(shù)進(jìn)行更新,此處為了簡單叉趣,就直接用了增量賦值
使用defaultdict()的解法
其實上一種方法中用counter()屬于大材小用泞边,我們需要的只是實現(xiàn)了__missing__方法的dict類即可,在這里我們可以調(diào)用collections模塊下的defaultdict()方法來幫助我們完成疗杉。
實現(xiàn)原理阵谚,defaultdict()在實例化的時候,需要傳入一個可調(diào)用對象烟具,這個可調(diào)用對象在__getitem__方法找不到鍵的時候被調(diào)用梢什,讓__getitem__方法返回某種默認(rèn)值
from collections import defaultdict
from math import ceil
def total_cost(calls):
dict1 = defaultdict(int)
for call in calls:
date, _, length = call.split(" ")
dict1[date] += ceil(int(length)/60)
return sum([i*2-100 if i>100 else i for i in dict1.values()])
此處直接傳入Int作為可調(diào)用對象是可行的,就是代碼有點丑朝聋,以后學(xué)了更加pythonic的寫法后再回來更新嗡午。