我有以下Python串列。[1, 1, 2, 2, 2, 3, 4, 4, 4]。我想創建一個函式,計算元素變化的索引。因此,例如,對于上述串列,該方法將產生這樣的結果--[2, 5, 6]--因為第一個 2 出現在索引 2,第一個 3 出現在索引 5,而第一個 4 出現在索引 6。
當然,有許多方法可以做到這一點。我將在更長的串列上每天運行這個方法數百萬次,所以我正在尋找最快速的解決方案。
以下是我目前所做的作業:
idxs = [i for i in range(len(inputList)) ]
dict_ = {v: i for v, i in zip(inputList, idxs)}
result = [v 1 for v in dict_.values() ]
然而,在輸入有先前使用過的值的串列時有一個錯誤,例如[1, 1, 2, 2, 2, 3, 4, 4, 1, 1]。
uj5u.com熱心網友回復:
你可以列舉你的值,并檢查[i-1]值是否與[i]值不同。
>>> inputList = [1, 1, 2, 2, 2, 3, 4, 4, 4 ]
>>> [i for i, val in enumerate(inputList) ifi> 0 and inputList[i-1] ! = val]。
[2, 5, 6]
而用你的第二個例子
>>> inputList = [1, 1, 2, 2, 2, 3, 4, 4, 4, 1, 1]
>>> [i for i, val in enumerate(inputList) ifi> 0 and inputList[i-1] ! = val]。
[2, 5, 6, 9]
這將在O(N)時間內運行,這是這種型別的演算法可能執行的最快速度。
uj5u.com熱心網友回復:
因此,在一些大型資料上進行的一點分析表明,僅僅通過避免在串列理解中每次檢查i > 0就可以做出一些改進。 這與 numpy 相當,盡管我們在轉換為 numpy 陣列和回傳時可能會損失很多:
100 1000
num_runs =1000
test_list = [1, 1, 2, 2, 2, 3, 4, 4, 4]
test_result = [2, 5, 6]
input_list = sum(([random.randint(0, max_value)] * random. randint(min_run, max_run) for _ in range(num_runs)), [])
def method_1(input_list)。
return [i for i, val in enumerate(input_list) if i> 0 and input_list[i-1] ! = val]。
def method_2(input_list)。
return [i for i in range(1, len(input_list)) if input_list[i-1] != input_list[i] ]
def method_3(input_list)。
return [i 1 for i, (a, b) in enumerate(zip(input_list, input_list[1: ])) if a != b]。
def method_4(input_list)。
input_array = np.array(input_list)
res, = np.where(input_array[:-1] != input_array[1:] )
res = 1] !
return list(res)。
def method_5(input_list)。
return [i 1 fori, val in enumerate(input_list[1: ]) if input_list[i]! = val]。
assert method_1(test_list) == test_result
assert method_2(test_list) == test_result
assert method_3(test_list) == test_result
assert method_4(test_list) == test_result
assert method_5(test_list) == test_result
print(timeit. timeit("method_1(input_list)", globals=globals(), number=10)
print(timeit. timeit("method_2(input_list)", globals=globals(), number=10)
print(timeit. timeit("method_3(input_list)", globals=globals(), number=10)
print(timeit. timeit("method_4(input_list)", globals=globals(), number=10)
print(timeit. timeit("method_5(input_list)", globals=globals(), number=10)
import random
import timeit
import numpy as np
max_value = 100
這就得到了結果:
這就得到了結果。
0.4418060999996669。
0.3605320999995456
0.3416827999972156
0.2726910000019416
0.2845658000005642
uj5u.com熱心網友回復:
下面是一個只使用range和len的答案,沒有使用enumerate,否則與Cory Kramer的答案類似:
inputList = [1, 1, 2, 2, 2, 3, 4, 4, 4, 1, 1]
idxs = [i for i in range(1, len(inputList)) if inputList[i-1] != inputList[i]]
print(idxs)
# [2, 5, 6, 9]/span>
這些解決方案在運行時間上是相似的,但是只使用range和len,而不使用enumerate會快一些:
import timeit
t = timeit.Timer("idxs = [i for i in range(1, len(inputList)) if inputList[i-1] != inputList[i]]"/span>。
"import random; random.seed(42); inputList = [random.ranrange(4) for i in range(1000000)]")
print('range len:'/span>, t.timeit(100)
t = timeit.Timer("[i for i, val in enumerate(inputList) if i>0 and inputList[i-1]!= val]",
"import random; random.seed(42); inputList = [random.ranrange(4) for i in range(1000000)]"/span>)
print('enumerate:'/span>, t.timeit(100)
# range len: 15.435243827
# enumerate: 17.243516137[/span>
轉載請註明出處,本文鏈接:https://www.uj5u.com/yidong/308537.html
標籤:
