Re: [問題]不用for迴圈尋找陣列中只出現過一次的資料

看板Python作者 (亮)時間10年前 (2014/05/12 03:22), 10年前編輯推噓2(206)
留言8則, 3人參與, 最新討論串3/5 (看更多)
※ 引述《sariel0322 (sariel)》之銘言: : 我想要請問一下,如果我有一串數字 : A = [9,5,5,4,7,6,4,1,2,0,10,9,7,....] : 要如何找出這列資料中只出現一次的數字,但不用到for迴圈的方法 (冏冏,我看成有出現就好…… 明天再補了 > <) 完整檔案見 IPython Notebook http://nbviewer.ipython.org/gist/ccwang002/bc1b047d0eca2c8f8bdd 這真的要快的話,就不應該自己寫 for loop,所以我想得到最快的方法就是用 set(A) 但有沒有更快的方式呢?其中一個可能是用 Cython, cffi 自己刻一個, 但 numpy.unique() 不知道快不快? 直覺上以為是會快很多的,所以來個實測。 # Test by IPython on Python 3.4 import numpy as np LEN = 10**7 # 約需要總共 200MB 的記憶體 # 整數 A = np.random.randint(0, 100, LEN) # numpy 陣列 (ndarray) A_list = A.tolist() # 一般的 list %timeit -n 5 np.unique(A) # numpy 解法 %timeit -n 5 set(A_list) # set() 解法 %timeit set(A) # 混用,對 numpy 陣列用 set() # 448ms, 232ms, 1.67s # 5.18s, 2.31s, - s if LEN = 10**8 結果 set() 跑得比 np.unique() 還快,蠻驚訝的 > < 資料量調大仍舊相同的趨勢。 混用很可怕,這小測試暗示 ndarray 用內建函式的時候,很可能會做非常多轉換, 很容易拖慢速度。而內建的指令其實速度飛快。 但這樣 numpy 哪裡有優勢,是否該洗洗睡?我猜它在浮點數表現就會好很多, 浮點數找相同的數值有點怪,但總之要幫 numpy 平反也不管這麼多了xd # 浮點數版本,只會有 0.0, 0.1, 0.2, ... A = np.random.randint(0, 100, LEN) / 10 A_list = A.tolist() %timeit -n 5 np.unique(A) %timeit -n 5 set(A_list) %timeit -n 5 set(A) # 698ms, 1.55s, 2.23s 果然 numpy 的效率就好很多。 恩…總之蠻好玩的。 PS Py 3.4 中多了 tracemalloc module 可以追蹤程式執行間記憶體用量 https://docs.python.org/3/library/tracemalloc.html 看 Python 物件記憶體用量(?) 可用 sys.getsizeof(obj) 看 Numpy .............. 可用 ndarray_obj.nbytes -- PyCon APAC 2014/TW is coming! May 17-18 @中研院人社館 More info on https://tw.pycon.org/2014apac/zh/ -- ※ 發信站: 批踢踢實業坊(ptt.cc), 來自: 140.112.217.22 ※ 文章網址: http://www.ptt.cc/bbs/Python/M.1399836156.A.6F6.html

05/12 11:09, , 1F
05/12 11:09, 1F

05/12 11:22, , 2F
關於記憶體用量, 筆記中有些地方我不懂
05/12 11:22, 2F

05/12 11:23, , 3F
為什麼用 numpy 做出 A 之後, 記憶體用量還不大; 做出 A.list
05/12 11:23, 3F

05/12 11:24, , 4F
之後, A.nbytes 就隨之暴增了? A.nbytes 是 A 物件的大小對嗎
05/12 11:24, 4F

05/12 11:24, , 5F
所以可以理解成 A (numpy obj) 會在被操作時多做些事情?
05/12 11:24, 5F
喔喔,我的猜測是 tracemalloc 它是在 python 分配記憶體的時候多加一個 hook 來記錄每行程式記憶體的增減,但 numpy 在 malloc 的時候不是用 python 的版本 所以 tracemalloc 裡會看不到 A (numpy obj) 的大小。 如果要看的話就要使用 numpy API 的 A.nbytes。 不過這個問題可能在 Py 3.5 + numpy 1.9(2.0?) 就會被解決了,python mail list 已經在討論相關的可行性 http://bugs.python.org/issue21233 http://mail.scipy.org/pipermail/numpy-discussion/2014-April/069935.html 但我蠻意外的是兩者的大小竟然差不多 我以為 numpy 的實作記憶體用量會小 list 的不少,是不是我搞錯什麼了 @@

05/12 21:30, , 6F
python set 的實作是用 C 寫的,使用 hash 演算法
05/12 21:30, 6F

05/12 21:30, , 7F
python list 所佔用的記憶體大小是 header +
05/12 21:30, 7F

05/12 21:31, , 8F
指標大小*預留空間大小,所以也不算太佔空間
05/12 21:31, 8F
感謝分享! ※ 編輯: ccwang002 (140.112.129.20), 05/14/2014 11:34:06
文章代碼(AID): #1JRytyRs (Python)
討論串 (同標題文章)
文章代碼(AID): #1JRytyRs (Python)