Re: [問題] 如何比較list裡面各項數字的大小並重組?
→
08/01 01:35,
08/01 01:35
→
08/01 01:36,
08/01 01:36
→
08/01 01:36,
08/01 01:36
→
08/01 01:37,
08/01 01:37
→
08/01 01:39,
08/01 01:39
→
08/01 01:42,
08/01 01:42
直覺這種東西本來就很主觀, 重點是不能為了直覺犧牲太多效率
需要會最少東西的寫法應該是
result = []
for i in range(0, len(s)): # 陣列很長時應改用 xrange
if s[i] > t[i]:
result.append(t[i])
else:
result.append(s[i])
當然這基本上是 O(n) 所以大方向對了, 不過還是有幾個問題
1. 做了 len(s) 次 index lookups
Subscript syntax 基本上是做 random access, 速度不如 iterator
當次數大時效率會有明顯落差
2. 對不等長陣列的支援不好, 如果要加上更多判斷, 可讀性會慢慢下降
3. 出來的東西只能是陣列, 如果你之後還要 iterate 它, 等於做了白工多轉換一次
4. 擴充性不佳, 例如如果以後要多比較一個陣列 r 就會炸裂
針對最後一點, 所以我們必須學習內建的 min 和 max
這裡可以用 min 來改寫
result = []
for i in range(len(s)): # 只給一個參數就預設是從 0 開始
result.append(min(s[i], t[i]))
事實上我覺得即使初學者, 最低限度也要寫成這樣, 更差的都不及格
第三點可以改成 generator 或輸出 iterator 來解決
例如包成 generator...
def generate_mins(list1, list2):
for i in range(len(list1)):
yield min(list1[i], list2[i])
result = generate_mins(s, t)
不過 yield 算進階語法, 為了不用更常用的語法而先學是本末倒置, 所以跳過
另外一種產生方法就等於要學 list comprehension 了
result = (min(s[i], t[i]) for i in range(0, len(s)))
只差在有沒有在這裡直接轉成 list (改用方括弧而非原括弧包起來) 而已
第二點稍後討論, 先講第一點
寫資料處理的程式時, iteration 的速度基本上決定了你的程式價值
即使再怎麼優美或容易維護或怎樣, 你處理速度慢人家超過一定程度就等於垃圾
所以各種語言才會用各式各樣的方法為非連續記憶體的 list loop-through 加速
Python (和其他很多語言) 的做法就是使用 foreach 語法
寫 for i in a_list: i 效率就是會優於 for i in range(a_list): a_list[i]
所以我們要做的是想辦法同時 iterate 複數個 lists, 而不是改用 suubscription
Python 提供的解決方案就是 zip 與自動 tuple 展開
所以繼續改寫...
result = (min(i[0], i[1]) for i in zip(s, t))
自動展開
result = (min(a, b) for a, b in zip(s, t))
這樣就有基本的樣子了
或者 如果你了解到其實 min 其實可以直接吃 iterable...
result = (min(i) for i in zip(s, t))
關於第二點, zip 有一個額外性質是會自動 trim-up
當輸入的 lists 不等長, 會自動把多的丟掉
如果你不喜歡這個行為, 而希望當某個 list 不夠長時提供預設值
則可以使用 itertools module 裡的 izip_longest
from itertools import izip_longest
result = (min(i) for i in izip_longest(s, t, float('inf')))
float('inf') 會產生「無窮大」, 所以這等於如果有陣列不夠長就無視它
順帶一題, 如果輸入陣列太長, zip 也有可能會有速度問題
這時候可以改用 itertools 的 izip
這樣我們就有了一個效率很好, 可讀性也優良的寫法
大部分人也都是這樣推薦
======
前面有人提出 map 的寫法
map(min, zip(s, t, u))
這也合理, 不過 map 在 Python 3 的行為有改, 要注意
Python 基本上比較不喜歡這類 function-oriented 的語法
這是 Guido 的個人偏好...
--
「我最想要的同伴嘛,首先是要笑口常開,其次是我們能永遠不會發生誤會。
如果這些都能辦到的話,嗯,如果他是世界上第一流的橋手,也還不錯。」
-- 班尼多‧加羅素,前義大利藍隊成員
--
※ 發信站: 批踢踢實業坊(ptt.cc)
◆ From: 140.112.94.61
推
08/01 11:48, , 1F
08/01 11:48, 1F
→
08/01 12:08, , 2F
08/01 12:08, 2F
推
08/01 12:40, , 3F
08/01 12:40, 3F
推
08/01 12:51, , 4F
08/01 12:51, 4F
推
08/01 12:53, , 5F
08/01 12:53, 5F
推
08/01 14:03, , 6F
08/01 14:03, 6F
※ 編輯: uranusjr 來自: 140.112.94.61 (08/01 14:42)
推
08/01 17:01, , 7F
08/01 17:01, 7F
推
08/01 17:12, , 8F
08/01 17:12, 8F
→
08/01 17:12, , 9F
08/01 17:12, 9F
討論串 (同標題文章)
本文引述了以下文章的的內容:
完整討論串 (本文為第 3 之 5 篇):