簡體   English   中英

大多數pythonic檢查列表的方法歸結為一個值

[英]Most pythonic way to check list boils down to one value

我想要一個 function check來檢查給定list是否減少(“歸結”)到給定 function reduce_function下的一個值。 (一個常見的例子可能是檢查列表列表是否僅包含相等長度的子列表。)

我至少看到了以下三種方法來實現這一點。 對於他們每個人,我都看到了一些優點和缺點。 在我看來,它們中的任何一個都沒有真正的可讀性。 你能給我一個詳細的概述:

哪一個會被認為是最具可讀性和最“pythonic”的?

1. 測量一組縮減值的長度。

這似乎最易讀,但需要reduce_function返回一個哈希值:

def check(lst):
    return len(set(map(reduce_function, lst))) == 1

2.統計組數

def check(lst):
    return len(list(itertools.groupby(lst, key=reduce_function)) == 1

3. 使用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

盡管如此,這仍然會評估整個lstreduce_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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM