python之統計字串中的字元個數
阿新 • • 發佈:2019-02-18
1.貼題
題目來自MOOC
《用Python玩轉資料》(南京大學)
第三週程式設計作業
定義函式countchar()按字母表順序統計字串中所有出現的字母的個數(允許輸入大寫字元,並且計數時不區分大小寫)。形如:
def countchar(str):
... ...
return a list
if __name__ == "__main__":
str = input()
... ...
print(countchar(str))
輸入格式:
字串
輸出格式:
列表
輸入樣例:
Hello, World!
輸出樣例:
[0, 0, 0, 1, 1, 0, 0, 1, 0, 0, 0, 3, 0, 0, 2, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0]
時間限制:500ms記憶體限制:32000kb
2.說明
這道題確實費了一些功夫。
思路為以字母為key,出現次數為value建立字典,然後根據輸入的字串呼叫函式輸出value值。(此處有一個坑,在後面說明)。
3.參考程式碼
def countchar(st): #定義數個數的函式
keys = [chr(i+97) for i in range(26)] #生成26個字母的key列表
di = dict().fromkeys(keys,0 ) #賦給每個key初始值0
new = [] #建立一個新列表用於存放有序的key
st = st.lower() #將所有輸入的字元改為小寫
for s in st: #遍歷字串
di[s] = st.count(s) #輸出每個字元的個數,存放到字典裡
for k in keys: #遍歷keys,將其在di中的值新增到新列表,獲得有序的26個字母的個數
new.append(di[k])
return new #返回存有26個字母個數的列表
if __name__ == "__main__":
st = input() #輸入字串
str1 = "" #定義一個空字串
for s in st: #遍歷輸入的字串
if s.isalpha() != 0: #只有字母才新增到新字串,標點忽略不計
str1 += s
print(countchar(str1)) #輸出列表
4.程式碼的注意點
生成26個字母的程式碼一開始沒想到要怎麼寫,直接手寫的
keys=["a","b","c","d","e","f","g","h","i","j","k","l","m","n","o","p","q","r","s","t","u","v","w","x","y","z"]
然後遭到了吐槽。。
命名dict的時候直接使用了dict,使用了python的保留字,雖然沒有出錯,但是還是遭到了無情的吐槽。。
- 賦給每個元素初值的時候不記得具體怎麼寫了,查資料找到了通過fromkeys設定多個鍵的值
- 鞏固了將所有字元改為小寫的寫法 str.lower()
- 實際使用了字串的count函式 str.count(要數的字元或字串)
- 字典的key在字典裡面的排序是無序的,因為沒有注意到這一點,剛開始的程式碼是錯的,因為輸出來的列表順序不對,請教了才修改正確的,增加了遍歷然後新增到新列表的程式碼
- 無視標點既可以建立一個含有各種特殊字元的字串然後使用remove函式,如果只要求計數字母(或者只計數字)的時候,就可以使用專門的isalpha或者isdigit函式。相關資料Python isalpha()方法
- 還有就是被吐槽使用count函式然後又有遍歷迴圈的話會讓程式的執行很慢。。@weixin_42047817
5.更好的程式碼
參考了以下幾篇人家的部落格
把程式碼修改為如下
def countchar(str):
alist = []
for i in range(26): #初始化一個長度為26,值均為0的列表
alist.append(0)
str = str.lower()
for i in str: #遍歷字串,如果是字母,則利用ascii碼值轉換為數字再平移至0-26範圍內,將對應的列表值加一
if i.isalpha():
alist[ord(i)-97] += 1
return alist
if __name__ == "__main__": #主函式部分與原始碼相同
st = input()
str1 = ""
for s in st:
if s.isalpha() != 0:
str1 += s
print(countchar(str1))
6.程式碼執行速度
在要統計的字串為
st = "".join([chr(i+96)*i*100 for i in range(1,27)])
時,3的程式碼和5的程式碼的執行速度結果如下
3程式碼
[100, 200, 300, 400, 500, 600, 700, 800, 900, 1000, 1100, 1200, 1300, 1400, 1500, 1600, 1700, 1800, 1900, 2000, 2100, 2200, 2300, 2400, 2500, 2600]
time: 1.108361 s
5程式碼
[100, 200, 300, 400, 500, 600, 700, 800, 900, 1000, 1100, 1200, 1300, 1400, 1500, 1600, 1700, 1800, 1900, 2000, 2100, 2200, 2300, 2400, 2500, 2600]
time: 0.023698 s
確實速度相差50倍多啊。。
附3程式碼測試程式碼
import time
def countchar(st):
keys = [chr(i+97) for i in range(26)]
di = {}.fromkeys(keys,0)
new = []
st = st.lower()
for s in st:
di[s] = st.count(s)
for k in di:
if k in keys:
new.append(di[k])
return new
if __name__ == "__main__":
st = "".join([chr(i+96)*i*100 for i in range(1,27)])
str1 = ""
start = time.clock()
for s in st:
if s.isalpha() != 0:
str1 += s
print(countchar(str1))
end = time.clock()
print("time: %f s" % (end - start))
7.最後存檔錯誤程式碼
下面的程式碼是不正確的!!!
錯誤原因(沒有考慮到字典內部儲存的時候是無序的)
def countchar(st):
keys = ["a","b","c","d","e","f","g","h","i","j","k","l","m","n","o","p","q","r","s","t","u","v","w","x","y","z"]
dict = {}.fromkeys(keys,0)
st = st.lower()
for s in st:
dict[s] = st.count(s)
return list(dict.values())
if __name__ == "__main__":
st = input()
str1 = ""
for s in st:
if s.isalpha() != 0:
str1 += s
print(countchar(str1))