我希望函数check
检查给定的list
在给定的函数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])
这可能是基于观点的,但是也有客观的理由支持或反对不同的选择。在这里,我将重点介绍第一个和第三个。
第一种方法转换为set
并测试其长度,恕我直言是最干净的,但是它有O(n)个额外的空间要求(在最坏的情况下,所有元素都not
lst
实际上是list
时有效。 以当前形式由于[...]
中的列表理解all
,第三种方法也具有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
尽管,即使已经明确存在多个不同的值,它仍将对整个
reduce_function
求值lst
。
我喜欢所有3个选项,尽管第三个选项不必是列表理解,只需取下方括号即可。
如果要检查是否可以将所有值都减小为相同的值,则无需遍历整个列表。一旦发现一个不等于列表中第一个值的值,就可以停止。会更有效: