1. 程式人生 > >python 列表、字典、集和、生成式

python 列表、字典、集和、生成式

##################### 列表生成式 練習 #################


import math
# 1. 找出1~10之間所有偶數, 並且返回一個列表, (包含以這個偶數為半徑的圓的面積)
#
# 1). 1~10之間所有偶數: range(2,11,2), 返回[2,4,6,8,10];

# **************方法1: 程式碼笨重, 這種型別建議改寫為列表生成式
# li = []
# for r in range(2,11,2):  #[2,4,6,8,10]
#     square = math.pi * r * r
#     li.append(square)
# print(li)
#
#
# *****方法2: 列表生成式實現
# print([math.pi * r * r for r in range(2,11,2)])

# *****方法3: 列表生成式實現, 將要返回的操作抽象為一個函式.
def square(r):
    """求以r為半徑的圓的平方"""
    res =  math.pi * r * r
    return res
print([square(r) for r in range(2,11,2)])


# 2. 找出1~10之間所有奇數, 並且返回一個列表, (所有的奇數轉換為字串)
print([str(i) for i in range(1,11,2)])


# 3. 找出1~100之間所有的質數.
def isPrime(num):


    """
    判斷num是否為質數, 如果為質數, 返回True, 否則返回False;
    什麼是質數?
        只能被1和本身整除的數, 就是質數.
        方法:迴圈:
            依次判斷num能否被(2,num)整除,
            如果能被其中一個數整除,不是質數.
            當迴圈結束, 都沒有發現能被整除的數, 那麼就是質數.
    """

  def isPrime(num): 
    for i in range(2, num):
        if num % i == 0:
            return  False
    else:
        return True

print([i for i in range(2,101) if isPrime(i)])

# 4. 找出1~100之間所有奇數, 並且返回一個列表,
#                   (如果能被3整除, 返回返回該數的平方, 否則返回該數的三次方)

print([i**2 if i%3==0 else i**3 for i in range(1,101,2)])

# 5. 給定一個列表li = [2,3,4,5,6,3,1,4,5],
#       如果是偶數返回0, 如果是奇數返回1

li = [2,3,4,5,6,3,1,4,5]
print([1 if i%2!=0 else 0 for i in li])

#########################2017 騰訊筆試程式設計題 ###############

"""

# 4. (2017-騰訊-線上程式設計題)

- 題目描述:

給定一個正整數,編寫程式計算有多少對質數的和等於輸入的這個正整數,並輸出結果。輸
入值小於1000。
如,輸入為10, 程式應該輸出結果為2。(共有兩對質數的和為10,分別為(5,5),(3,7))
# [2,3,5,7]

- 輸入描述:
輸入包括一個整數n,(3 ≤ n < 1000)

- 輸出描述:
輸出對數

- 示例1 :

```
輸入:
    10
輸出:
    2

```

"""


num = int(input("N:"))  # 10
# 1). 判斷2~num之間有多少個質數?
def isPrime(num):
    for i in range(2, num):
        if num % i == 0:
            return  False
    else:
        return True
primeLi =  [i for i in range(2,num) if isPrime(i)]
print(primeLi)


# 判斷素數列表primeLi中有多少個素數對等於num
primePairCount = 0

# [2,3,5,7]
# 思路, 效率不高:
#       1). 先從列表中拿出兩個數;
#       2). 判斷兩個數之和是否等於num
# for item1 in primeLi:
#     for item2 in primeLi:
#         if item1 + item2 == num and item1 <= item2:
#             primePairCount += 1
# print(primePairCount)


# 思路:
# [2,3,5,7]   # 2===== 10-2; 3====10-3, 5====10-5, 7====10-7
for item1 in primeLi:
    if (num -item1) in primeLi and item1 <= num-item1:
        primePairCount += 1
print(primePairCount)

############################ 實現矩陣轉置 ###########################

# 實現矩陣轉置的兩種方式
#   1). 列表生成式
#   2). 內建函式zip

li = [
    [1,2,3,3,4],
    [4,5,6,2,1],
    [7,8,9,1,2]
]
# 方法1:
print([[ row[columnIndex] for row in li] for columnIndex in range(5)])
# columnIndex=0=====> 返回的是每一行的第0個索引值; [1,4,7]
# columnIndex=1=====> 返回的是每一行的第0個索引值; [2,5,8]

# 方法2:
#     *li: 解包
#     zip:
#           1).打包函式, 用於將可迭代的物件作為引數,
#           將物件中對應的元素打包成一個個元組,
#           然後返回由這些元組組成的列表。
#           2).如果各個迭代器的元素個數不一致,則返回列表長度與最短的物件相同,
#           利用 * 號操作符,可以將元組解壓為列表
#           3). zip 方法在 Python 2 和 Python 3 中的不同:
#           在 Python 3.x 中為了減少記憶體,zip() 返回的是一個物件。
#           如需展示列表,需手動 list() 轉換。
# print(list(zip(*li)))

####################### 字典生成式 #################
# 需求1: 假設有20個學生,學生分數在60-100之間,篩選出成績在90分以上的學生

import random

# stuInfo={}
# for i in range(20):
#     # name = "westos"+ str(i)
#     # score = random.randint(60,100)
#     # stuInfo[name] = score
#     stuInfo["westos"+ str(i)] = random.randint(60,100)
# print(stuInfo)


stuInfo = {"westos"+ str(i):random.randint(60,100)
            for i in range(20)}

# 篩選出score>90

# highScore = {}
# for name, score in stuInfo.items():
#     if score > 90:
#         highScore[name] = score
# print(highScore)

print({ name:score for name, score in stuInfo.items() if score > 90 })

# 需求2:
"""                                                                                                           
** 需求:
    假設已有若干使用者名稱字及其喜歡的電影清單,
    現有某使用者, 已看過並喜歡一些電影, 現在想找
    新電影看看, 又不知道看什麼好.
** 思路:
    根據已有資料, 查詢與該使用者愛好最相似的使用者,
    即看過並喜歡的電影與該使用者最接近,
    然後從那個使用者喜歡的電影中選取一個當前使用者還沒看過的電影進行推薦.
    
    
 

 100:    
userInfo = {
    'user1':{'file1', 'file2', 'file3'},
    'user2':{'file2', 'file2', 'file4'},
}    
"""

# # 1. 隨機生成電影清單
# import random
# data = {}   # 儲存使用者及喜歡電影清單的資訊;
# for userItem in range(100):
#     files = set([])
#     for fileItem in range(random.randint(4,15)):
#         files.add( "film" + str(fileItem))
#     data["user"+str(userItem)] = files
# print(data)
#
import pprint
pprint.pprint({
    "user"+str(userItem):
        {"film" + str(fileItem) for fileItem in range(random.randint(4,15))}
        for userItem in range(100)   })



# 3. 將字典的key值和value值調換;
 

d = {'a':'apple', 'b':'bob', 'c':'come'}

print({v:k for k,v in d.items()})
print({k:k.upper() for k,v in d.items()})


# 4.大小寫計數合併 : key值最終全部為小寫.
 

d1 = {'A':10, 'b':3, 'a':5, 'B':8, 'd':1}

print({k.lower(): d1.get(k.upper(),0)+d1.get(k.lower(),0) for k,v in d1.items()})
#get( k.upper(),0) 當沒有大寫時 返回0
# print({k.lower(): d1[k.upper()]+d1[k.lower()] for k,v in d1.items()})  # 報錯

########################## 集和生成式 #########################
 

s = {1,2,3,4,5,6,7}
# 集合生成式
print({i**2 for i in s })
# 字典生成式
print({i:i**2 for i in s })

 

########################### 生成器 列表生成式的改寫 ################
 

# 1). 判斷2~num之間有多少個質數?
def isPrime(num):
    for i in range(2, num):
        if num % i == 0:
            return  False
    else:
        return True
# primeLi =  [i for i in range(1,1000) if isPrime(i)]
# print(primeLi)

# 生成器最快實現的方式:通過列表生成式改寫. 一邊迴圈, 一邊計算的機制.
primeLi =  (i for i in range(2,1000) if isPrime(i))
# print(next(primeLi))
# print(next(primeLi))
# print(next(primeLi))
# print(next(primeLi))


from collections import  Iterable
for i in primeLi:
    print(i)

# print(isinstance(primeLi,Iterable))  # 判斷是否可以for迴圈

########################## Fibnnian 數列 ######################

"""

** 歷史
斐波那契數列(Fibonacci sequence),又稱黃金分割數列、因數學家列昂納多·斐波那契(Leonardoda Fibonacci)
以兔子繁殖為例子而引入,故又稱為“兔子數列”,指的是這樣一個數列:1、1、2、3、5、8、13、21、34、……在數學上,
斐波納契數列以如下被以遞推的方法定義:F(1)=1,F(2)=1, F(n)=F(n-1)+F(n-2)(n>=2,n∈N*)
在現代物理、準晶體結構、化學等領域,斐波納契數列都有直接的應用,為此,美國數學會從1963年起出版了以
《斐波納契數列季刊》為名的一份數學雜誌,用於專門刊載這方面的研究成果。


** 數列內容
斐波那契數列指的是這樣一個數列 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233,377,
610,987,1597,2584,4181,6765,10946,17711,28657,46368........


"""

# yield: 當函式中包含yield關鍵字, 返回值是一個生成器, 如果要執行函式內容.需要呼叫next方法, 或者for迴圈.
#         執行過程: 當執行next方法時, 遇到yield程式停止, 直到執行下一次next方法時,
#          從上一次停止的yield處繼續執行,遇到yield停止執行.
# return: 遇到return函式執行結束;# num=1

def fib(num):
    """將來顯示幾個fib數列"""
    # count代表顯示的已經
    # a代表第一個數, b代表第二個數, count代表已經顯示的fib個數,當前為0.
    a,b,count = 0,1,0
    # 如果當前顯示的個數小於需要顯示的格式, 則顯示b, 並且計算出下一個要顯示的數。
    while count < num:
        yield  b
        a, b = b, a+b
        # 已經顯示的次數加1;
        count += 1


# 生成器: 如果函式中有yield, 那麼這個函式的返回值就是一個生成器;
res=fib(100)
print(next(res))
print(next(res))


# 生成器fib()執行的過程分析:
#       執行語句 f = fab(100) 時,並不會馬上執行 fib() 函式的程式碼塊,而是首先返回一個 iterable 物件(即生成器)!
#       在 for 迴圈語句執行時或者next(),才會執行 fib() 函式的程式碼塊。
#       執行到語句 yield b 時,fib() 函式會返回一個迭代值,直到下次迭代前,
#       程式會回到 yield b 的下一條語句繼續執行,然後再次回到 for 迴圈,如此迭代直到結束。
#       看起來就好像一個函式在正常執行的過程中被 yield 中斷了數次,每次中斷都會通過 yield 返回當前的迭代值。
# 由此可以看出,生成器通過關鍵字 yield 不斷的將迭代器返回到記憶體進行處理,而不會一次性的將物件全部放入記憶體,
# 從而節省記憶體空間。
#
#
#

############################# 生成器 實現迷你聊天機器人 ###############

# 生成器可以使用的方法:
#       - next(g)
#       - g.send(''), 給生成器傳遞值;
#               給yield所在位置傳送一個數據, 直到遇到下一個yield停止.


# def fun():
#     while True:
#         print("welcome......")
#         receive = yield  "hello"
#         print(receive)
# # ***fun返回值是一個生成器物件.(因為函式中包含yield關鍵字)
# f = fun()
# print(f)
# print(next(f))
# f.send("微信")

def chat_robot():
    res = ''
    while True:
        receive = yield res
        if 'age' in receive:
            res = "年齡保密"
        elif 'name' in receive:
            res = "siri"
        else:
            res = "i don't know what you say"

def main():
    # 生成器物件
    Robot = chat_robot()
    next(Robot)
    while True:
        send_data = input("粉條>>:")
        if send_data == 'q' or send_data == 'bye':
            print("不聊了, 我也撤了.....")
            break
        print(Robot.send(send_data))

main()