简体   繁体   English

大多数pythonic检查列表的方法归结为一个值

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

I want a function check to check that a given list reduces ("boils down") to exactly one value under a given function reduce_function .我想要一个 function check来检查给定list是否减少(“归结”)到给定 function reduce_function下的一个值。 (A common example could be to check that a list of lists contains sublists of equal length only.) (一个常见的例子可能是检查列表列表是否仅包含相等长度的子列表。)

I see at least the three following ways to achieve this.我至少看到了以下三种方法来实现这一点。 For each of them, I see some advantages and disadvantages.对于他们每个人,我都看到了一些优点和缺点。 None of them really looks very readable to my eye.在我看来,它们中的任何一个都没有真正的可读性。 Could you give me an elaborate overview about:你能给我一个详细的概述:

Which one would be considered most readable and most "pythonic"?哪一个会被认为是最具可读性和最“pythonic”的?

1. Measure the length of the set of reduced values. 1. 测量一组缩减值的长度。

This seems most readable, but requires reduce_function to return a hashable:这似乎最易读,但需要reduce_function返回一个哈希值:

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

2. Count the number of groups 2.统计组数

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

3. Use all on comparison with first element 3. 使用all与第一个元素进行比较

This needs an additional or -statement (which could be replaced by an if - else -statement) to cover the case of lst being empty.这需要一个额外的or - 语句(可以用if - else - 语句代替)来覆盖lst为空的情况。

def check(lst):
    return not lst or all([reduce_function(el) == reduce_function(lst[0]) for el in lst])

I like all 3 options although the third doesn't need to be a list comprehension, just take the square brackets off.我喜欢所有 3 个选项,尽管第三个不需要是列表理解,只需去掉方括号即可。

Like your second option the itertools documentation has a recipe called all_equal that checks if all elements in an iterable are equal using itertools.groupby as well, although they didn't account for a custom function and defaulting to false when empty but it can easily be implemented:与您的第二个选项一样, 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 is the "pythonic" way to check if all elements are equal in an iterable; itertools.all_equal是检查迭代中所有元素是否相等的“pythonic”方法; I only modified it to fit your needs.我只是修改它以满足您的需求。

This is probably a bit opinion based, but there are also objective reasons for or against the different alternatives.这可能有点基于意见,但也有客观原因支持或反对不同的选择。 I'll focus on the first and third one here.我将在这里重点介绍第一个和第三个。

The first approach, converting to a set and testing it's length, is IMHO the cleanest, but it has O(n) additional space requirement (in the worst case of all elements being not the same).第一种方法,转换为一个set并测试它的长度,恕我直言,它是最干净的,但它有 O(n) 额外的空间要求(在所有元素相同的最坏情况下)。 It also works with any iterable, whereas the third one only works if lst is actually a list .它也适用于任何可迭代对象,而第三个仅适用于lst实际上是list In it's current form the third approach also has O(n) space complexity, too, (in all cases) due to the list comprehension [...] within the all ;在当前的形式中,第三种方法也具有 O(n) 空间复杂度,(在所有情况下)由于列表理解[...] all ; you can use a generator expression instead.您可以改用生成器表达式。 Further, reduce_function(lst[0]) is recomputed for each other element.此外, reduce_function(lst[0])为每个其他元素重新计算。 Finally, the not lst or is redundant, as all of an empty list is True .最后, not lst or是多余的,因为all空列表都是True

Also, note that if you want to test if the list "boils down" to at most one value, as implied by the not lst or , you should check len(...) <= 1 for the first two approaches.另外,请注意,如果您想测试列表是否“归结”为最多一个值,正如not lst or所暗示的那样,您应该检查前两种方法的len(...) <= 1


I did not test this, but I think this should work, and a) work with non-hashable reduce_function , b) be O(1) space complexity, c) work with lists or iterables, and d) respect the empty-list corner case:我没有对此进行测试,但我认为这应该可行,并且 a) 使用不可散列的reduce_function ,b) 是 O(1) 空间复杂度,c) 使用列表或可迭代对象,并且 d) 尊重空列表角案子:

def check(lst):
    return sum(1 for _ in itertools.groupby(lst, key=reduce_function)) <= 1

This will still evaluate reduce_function for the entire lst , though, even if it's already clear that there is more than one distinct value.尽管如此,这仍然会评估整个lstreduce_function ,即使已经很清楚存在多个不同的值。

If you want to check if all values can be reduced to the same value you don't need to go through the whole list.如果要检查是否所有值都可以减少到相同的值,则不需要通过整个列表 go。 You can stop as soon as you find a value that is not equal to the first element in the list.一旦发现不等于列表中第一个元素的值,您就可以停止。 It will be more efficient:它会更有效率:

def check(func, lst):
    it = iter(lst)
    first = func(next(it))
    for i in it:
        if func(i) != first:
            return False
    return True

You can also replace the for loop with the function all .您也可以用 function all替换for循环。 In your solution with all you calculate the first element in the list len(lst) + 1 times.在您的解决方案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.

相关问题 大多数Pythonic方法在O(1)复杂度的列表中查找/检查项目? - Most Pythonic way to find/check items in a list with O(1) complexity? 大多数“pythonic”方式来检查列表的子列表的排序? - Most “pythonic” way to check ordering of sub lists of a list? 以最pythonic的方式将列表列表复制到另一个列表的一部分中 - Copying a list of lists into part of another one in the most pythonic way 将列表中的值用作另一个列表的索引的最pythonic方法 - most pythonic way to use a value from a list as an index to another list 在列表中循环直到特定值的最pythonic方式是什么? - What is the most pythonic way of looping in a list until a particular value? 更新相同字典列表中的字典值的最pythonic方法? - Most pythonic way to update a dictionary value in a list of same dictionaries? 检查对象是否为数字的最pythonic方法是什么? - What is the most pythonic way to check if an object is a number? 检查列表是否已排序的 Pythonic 方法 - Pythonic way to check if a list is sorted or not 检查一维列表是否为二维列表的元素的大多数pythonic方法? - Most pythonic way to check if a 1-dimensional list is an element of a 2-dimensional list? 大多数pythonic方式转换元组列表 - Most pythonic way to convert a list of tuples
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM