![](/img/trans.png)
[英]Most Pythonic way to find/check items in a list with O(1) complexity?
[英]Most pythonic way to check list boils down to one value
我想要一個 function check
來檢查給定list
是否減少(“歸結”)到給定 function reduce_function
下的一個值。 (一個常見的例子可能是檢查列表列表是否僅包含相等長度的子列表。)
我至少看到了以下三種方法來實現這一點。 對於他們每個人,我都看到了一些優點和缺點。 在我看來,它們中的任何一個都沒有真正的可讀性。 你能給我一個詳細的概述:
哪一個會被認為是最具可讀性和最“pythonic”的?
這似乎最易讀,但需要reduce_function
返回一個哈希值:
def check(lst):
return len(set(map(reduce_function, lst))) == 1
def check(lst):
return len(list(itertools.groupby(lst, key=reduce_function)) == 1
all
與第一個元素進行比較這需要一個額外的or
- 語句(可以用if
- else
- 語句代替)來覆蓋lst
為空的情況。
def check(lst):
return not lst or all([reduce_function(el) == reduce_function(lst[0]) for el in lst])
我喜歡所有 3 個選項,盡管第三個不需要是列表理解,只需去掉方括號即可。
與您的第二個選項一樣, itertools
文檔有一個名為all_equal
的配方,它也使用itertools.groupby
檢查可迭代對象中的所有元素是否相等,盡管它們沒有考慮自定義 function 並且在為空時默認為 false 但它很容易實施的:
def all_equal(iterable, key=reduce_function):
g = groupby(iterable, key)
return next(g, False) and not next(g, False)
itertools.all_equal
是檢查迭代中所有元素是否相等的“pythonic”方法; 我只是修改它以滿足您的需求。
這可能有點基於意見,但也有客觀原因支持或反對不同的選擇。 我將在這里重點介紹第一個和第三個。
第一種方法,轉換為一個set
並測試它的長度,恕我直言,它是最干凈的,但它有 O(n) 額外的空間要求(在所有元素不相同的最壞情況下)。 它也適用於任何可迭代對象,而第三個僅適用於lst
實際上是list
。 在當前的形式中,第三種方法也具有 O(n) 空間復雜度,(在所有情況下)由於列表理解[...]
all
; 您可以改用生成器表達式。 此外, reduce_function(lst[0])
為每個其他元素重新計算。 最后, not lst or
是多余的,因為all
空列表都是True
。
另外,請注意,如果您想測試列表是否“歸結”為最多一個值,正如not lst or
所暗示的那樣,您應該檢查前兩種方法的len(...) <= 1
。
我沒有對此進行測試,但我認為這應該可行,並且 a) 使用不可散列的reduce_function
,b) 是 O(1) 空間復雜度,c) 使用列表或可迭代對象,並且 d) 尊重空列表角案子:
def check(lst):
return sum(1 for _ in itertools.groupby(lst, key=reduce_function)) <= 1
盡管如此,這仍然會評估整個lst
的reduce_function
,即使已經很清楚存在多個不同的值。
如果要檢查是否所有值都可以減少到相同的值,則不需要通過整個列表 go。 一旦發現不等於列表中第一個元素的值,您就可以停止。 它會更有效率:
def check(func, lst):
it = iter(lst)
first = func(next(it))
for i in it:
if func(i) != first:
return False
return True
您也可以用 function all
替換for
循環。 在您的解決方案all
,您計算列表中的第一個元素len(lst) + 1
次。
def check(func, lst):
it = iter(lst)
first = func(next(it))
return all(first == func(i) for i in it)
check(sum, [[0, 1], [0, 1], [0, 1]])
# True
check(sum, [[1, 1], [0, 1], [0, 1]])
# False
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.