[英]Python — list comprehension with try/exception and nested conditional
此代码应以O(n)线性时间找到列表的模式。 我想将其转换为列表理解,因为我正在自学Python,并试图提高列表理解能力。
这些内容翔实,但并不能真正回答我的问题:
我遇到的问题是嵌套if和try / except。 我确定这是一个简单的问题,所以初级Python程序员可能很快就能找到答案。
def mode(L):
# your code here
d = {}; mode = 0; freq = 0
for j in L:
try:
d[j] += 1
if d[j] > freq:
mode = j; freq = d[j]
except(KeyError): d[j] = 1
return mode
请注意, L
参数是一个如下的整数列表:
L = [3,4,1,20,102,3,5,67,39,10,1,4,34,1,6,107,99]
我在想类似的东西:
[try (d[j] += 1) if d[j] > freq (mode = j; freq = d[j]) except(KeyError): d[j] = 1 for j in L]
但是我没有足够的胶带来固定语法对这件事的影响。
我知道您正在学习理解,但是您可以使用默认字典或Counter来完成。
import collections
def mode(L):
# your code here
d = collections.defaultdict(lambda: 1); mode = 0; freq = 0
for j in L:
d[j] += 1
if d[j] > freq:
mode = j; freq = d[j]
return mode
更好的是,当您不尝试学习理解力时:
import collections
def mode(L):
collections.Counter(L).most_common(1)[0][0]
尽管可能无法直接在列表理解中执行此操作,但是也没有理由这样做。 您实际上只想在实际检索结果时检查错误。 因此,您确实想使用generator
而不是列表推导。
语法大致相同,只是使用括号而不是括号,因此您将执行以下操作:
generator = (do something)
try:
for thing in generator
except KeyError:
etc...
就是说,您确实不想为您的特定应用程序执行此操作。 您要使用一个计数器:
from collections import Counter
d = Counter(L)
mode = Counter.most_common(1)[0]
在列表理解中不能使用try-except
表达式。
引用此答案 :
列表理解中的异常是不可能处理的,因为列表理解是一个包含其他表达式的表达式,仅此而已(即没有语句,只有语句可以捕获/忽略/处理异常)。
编辑1:
try-except
使用try-except
子句try-except
,您可以做的是使用字典中的get
方法:
def mode(L):
d = {}
mode = 0
freq = 0
for j in L:
d[j] = d.get(j, 0) + 1
if d[j] > freq:
mode = j
freq = d[j]
return mode
从Python文档 :
get(key [,default]) :如果key在字典中,则返回key的值,否则返回default。 如果未提供default,则默认为None,因此此方法永远不会引发KeyError。
编辑2:
这是我的列表理解方法,不是很有效,只是为了好玩:
r2 = max(zip(L, [L.count(e) for e in L]), key = lambda x: x[1])[0]
您不能将try: except:
纳入列表理解中。 但是,您可以通过重构为dict
理解来解决它:
d = {i: L.count(i) for i in L}
然后,您可以在单独的测试中确定最大密钥和相应密钥。 但是,这将是O(n**2)
。
由于您尝试查找最常出现的值,因此使用max
可以轻松实现这一目的:
def mode(L):
return max(L, key=L.count)
这比其他建议使用collections.Counter
答案效率低(它是O(N^2)
而不是O(N)
),但是对于中等大小的列表,它可能足够快。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.