[英]subtraction of lists in python, optimising speed
為了找出python中兩個列表的替換,我使用:
names_of_files_not_dowloaded = [item for item in total_files if item not in names_of_files_downloaded]
有用。
列表的大小是:
文件總數56373個元素
下載的文件列表28464個元素
它持續34秒。 不知怎的,我有直覺說34秒太長了。 有沒有辦法更有效地進行減法?
謝謝
編輯:一個元素就像'AB12345'
列表沒有重復任何元素,它們已經設置好了
只需將files_downloaded
設置為一個集合而不是列表。 列表需要對列表進行完整迭代,以便每次要進行檢查時進行成員資格檢查 。 但是,設置查找效率要高得多 。
只需使用:
downloaded_set = set(files_downloaded)
list_of_files_not_dowloaded = [item for item in total_files if item not in downloaded_set]
將列表放入集合中會產生初始成本,但之后的成員資格檢查會更快。
@ juanpa.arrivillaga也是另一個原因對性能的影響是在評論中提到in
使用時設置在做字符串平等檢查,而哈希值進行比較,后者要便宜得多。
看來,如果我正在閱讀源代碼, CPython的列表會在檢查成員身份時使用直接相等檢查來進行比較 。 據推測,Sets使用哈希值,並且在Set創建時緩存它們。
如果您不關心元素的順序,並且您的列表不包含重復項,則可以使用:
diff = set(total_files) - set(files_downloaded)
如果您需要輸出作為列表:
diff = list(set(total_files) - set(files_downloaded))
set
覆蓋__sub__()
方法並將其用作設置差異,這正是您要查找的內容。
正如你的問題所說列表不包含dupes並且行為類似於集合,這應該可以獲得你想要的相對較好的性能。
total_files_set = set(total_files)
files_downloaded_set = set(files_downloaded)
files_not_dowloaded_set = total_files_set - files_downloaded_set
list_of_files_not_dowloaded = list(files_not_dowloaded_set)
或者如果你想要一行:
list_of_files_not_dowloaded = list(set(total_files) - set(files_downloaded))
要了解有關使用集合的所有操作的更多信息,可以在此處進行檢查
編輯 :
我嘗試使用2個隨機列表計時兩種方法
timeit.timeit('l = list(set(l1)-set(l2))',
setup='import random; l1 = random.sample(range(1000000), 100000); l2 = random.sample(range(1000000), 50000)',
number = 10)
輸出:
0.39393879500130424
timeit.timeit('l = [item for item in l1 if item not in l2]', \
setup='import random; l1 = random.sample(range(1000000), 10000); l2 = random.sample(range(1000000), 5000)', \
number = 1)
輸出:
98.58012624000003
如果您碰巧已經擁有兩個集合,而不必從列表轉換:
timeit.timeit('l = list(s2-s1)',
setup='import random; s1 = set(random.sample(range(1000000), 100000)); s2 = set(random.sample(range(1000000), 50000))',
number = 10)
輸出:
0.06160322100004123
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.