我想知道 的哪些元素list_1
在list_2
. 我需要輸出作為布爾的有序串列。但我想避免for
回圈,因為兩個串列都有超過 200 萬個元素。
這就是我所擁有的并且它可以作業,但是它太慢了:
list_1 = [0,0,1,2,0,0]
list_2 = [1,2,3,4,5,6]
booleans = []
for i in list_1:
booleans.append(i in list_2)
# booleans = [False, False, True, True, False, False]
我可以拆分串列并使用多執行緒,但如果可能的話,我更喜歡更簡單的解決方案。我知道 sum() 之類的一些函式使用向量運算。我正在尋找類似的東西。
如何讓我的代碼更有效率?
uj5u.com熱心網友回復:
我認為在更大的樣本輸入上實際計時此處介紹的一些解決方案會很有用。對于這個輸入和在我的機器上,我發現 Cardstdani 的方法是最快的,其次是該numpy
isin()
方法。
設定 1
import random
list_1 = [random.randint(1, 10_000) for i in range(100_000)]
list_2 = [random.randint(1, 10_000) for i in range(100_000)]
設定 2
list_1 = [random.randint(1, 10_000) for i in range(100_000)]
list_2 = [random.randint(10_001, 20_000) for i in range(100_000)]
計時- 從最快到最慢排序(設定 1)。
Cardstdani - 方法 1
我建議將 Cardstdani 的方法轉換為串列推導(請參閱
采用以下設定
import random
list_1 = [random.randint(1, n ** 2) for i in range(n)]
list_2 = [random.randint(1, n ** 2) for i in range(n)]
n
在 中變化[2 ** k for k in range(18)]
,我們得到類似的結果:
采用以下設定
import random
list_1 = list(range(n))
list_2 = list(range(n, 2 * n))
n
并變化[2 ** k for k in range(18)]
:
采用以下設定
import random
list_1 = [random.randint(1, n) for i in range(10 * n)]
list_2 = [random.randint(1, n) for i in range(10 * n)]
n
并變化[2 ** k for k in range(18)]
:
uj5u.com熱心網友回復:
您可以利用函式的O(1)
in 運算子復雜性來set()
提高 for 回圈的效率,因此您的最終演算法將O(n)
及時運行,而不是O(n*n)
:
list_1 = [0,0,1,2,0,0]
list_2 = [1,2,3,4,5,6]
s = set(list_2)
booleans = []
for i in list_1:
booleans.append(i in s)
print(booleans)
作為串列理解,它甚至更快:
s = set(list_2)
booleans = [i in s for i in list_1]
如果你只想知道元素,你可以使用這樣的集合的交集,由于使用了set()
函式,這將是一個有效的解決方案,已經被其他 Python 工程師優化:
list_1 = [0,0,1,2,0,0]
list_2 = [1,2,3,4,5,6]
print(set(list_1).intersection(set(list_2)))
輸出:
{1, 2}
此外,要提供串列格式輸出,您可以將結果集轉換為具有list()
函式的串列:
print(list(set(list_1).intersection(set(list_2))))
uj5u.com熱心網友回復:
如果你想使用向量方法,你也可以使用 Numpy isin。這不是最快的方法,正如oda 的優秀帖子所證明的那樣,但它絕對是一個值得考慮的替代方案。
import numpy as np
list_1 = [0,0,1,2,0,0]
list_2 = [1,2,3,4,5,6]
a1 = np.array(list_1)
a2 = np.array(list_2)
np.isin(a1, a2)
# array([False, False, True, True, False, False])
uj5u.com熱心網友回復:
您可以使用該map
功能。如果您不熟悉lambda函式,那么您可以檢查一下。
list_1 = [0,0,1,2,0,0]
list_2 = [1,2,3,4,5,6]
booleans = list(map(lambda e:e in list_2,iter(list_1)))
print(booleans)
輸出
[False, False, True, True, False, False]
map
但是,如果您想要唯一不同的元素,那么您可以使用filter
具有相同代碼的函式來代替函式。
list_1 = [0,0,1,2,0,0]
list_2 = [1,2,3,4,5,6]
new_lst = list(filter(lambda e:e in list_2,iter(list_1)))# edited instead of map use filter.
print(new_lst)
輸出
[1, 2]
已編輯
我正在in
從代碼中洗掉該陳述句,因為in
它也充當回圈。我正在使用該timeit
模塊進行檢查。
您可以將此代碼用于包含True
和的串列False
。
這種方式比上一種方式最快。
list_1 = [0,0,1,2,0,0]
list_2 = [1,2,3,4,5,6]
set_2 = set(list_2)
booleans = list(map(lambda e:set_2!=set_2-{e},iter(list_1)))
print(booleans)
輸出
[False, False, True, True, False, False]
這一個用于包含元素的串列。
list_1 = [0,0,1,2,0,0]
list_2 = [1,2,3,4,5,6]
set_2 = set(list_2)
booleans = list(filter(lambda e:set_2!=set_2-{e},iter(list_1))) # edited instead of map use filter
print(booleans)
輸出
[1,2]
作為 Op 從不使用 lambda 函式,那么這是給他的
list_1 = [0,0,1,2,0,0]*100000
list_2 = [1,2,3,4,5,6]*100000
set_2 = set(list_2)
def func():
return set_2!=set_2-{e}
booleans = list(map(func,iter(list_1)))
我知道我的方式不是回答這個問題的最佳方式,因為我從不使用NumPy
太多。
uj5u.com熱心網友回復:
僅使用內置的集合交集方法可能更簡單,但如果您有很多要比較的串列,那么對串列進行排序可能會更快。對串列進行排序是 n ln n,但是一旦對它們進行了排序,就可以通過檢查元素是否匹配來在線性時間內比較它們,如果不匹配,則前進到串列中當前元素較小的下一個專案。
uj5u.com熱心網友回復:
用于set()
獲取每個串列中唯一專案的串列
list_1 = [0,0,1,2,0,0]
list_2 = [1,2,3,4,5,6]
booleans = []
set_1 = set(list_1)
set_2 = set(list_2)
if(set_1 & set_2):
print(set_1 & set_2)
else:
print("No common elements")
輸出:
{1, 2}
uj5u.com熱心網友回復:
如果您知道這些值是非負的并且最大值遠小于串列的長度,那么使用 numpy 的 bincount 可能是使用集合的一個不錯的選擇。
np.bincount(list_1).astype(bool)[list_2]
如果碰巧是 numpy 陣列list_1
,list_2
這甚至可以比 set list-comprehension 解決方案快得多。(在我的測驗中為 263 μs 和 7.37 ms;但如果它們是 python 串列,它比設定的解決方案稍慢,為 8.07 ms)
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/465264.html