for i in range(len(q)):
# q.remove(max(q))
# maxi = max(q)
if((q.index(max(q)))+3) in range(len(q)):
return("Too chaotic")
if((q.index(max(q)))+2) in range(len(q)):
bribe = bribe + 2
q.remove(max(q))
elif ((q.index(max(q)))+1) in range(len(q)):
bribe = bribe + 1
q.remove(max(q))
elif(q.index(max(q))) == (len(q)-1):
q.remove(max(q))
return(bribe)
我想将上述for循环转换为列表理解。我尝试做
["Too chaotic" if((q.index(max(q)))+3) in range(len(q))
bribe+2,q.remove(max(q)) if((q.index(max(q)))+2) in range(len(q))
else [bribe+2,q.remove(max(q)] if((q.index(max(q)))+2) in range(len(q))
else q.remove(max(q)) if (q.inde (max(q))) == (len(q)-1) for i in
range(len(q))]
但是没有用。
答案 0 :(得分:0)
SO上有很多这样的问题:我如何将这段代码转换为列表/字典理解?我已经看到了三个主要目标:
但是有时候,我们根本不知道。在这里就是这种情况,因此,我将从通用思想入手。
按照重要性顺序,在创建列表理解之前,这是我的经验法则:
return
,break
,raise
,...)让我们尝试使用这些规则来解决您的问题。
要解决的第一件事是返回值的类型。根据情况,您可以返回字符串或整数。尽管Python不强制执行函数来键入一致性,但您应该避免这种混淆。您可以返回一个特殊值(-1
)或引发异常。
还有一些要解决的问题:
i
从未使用:用_
取代(请参阅What is the purpose of the single underscore "_" variable in Python?); q.index(max(q))
并将其存储在变量max_q_index
中; x in range(len(q))
的意思是0 <= x < len(q)
; 您得到:
for _ in range(len(q)):
m = max(q)
max_q_index = q.index(m) # position of the max
if max_q_index < len(q) - 3:
return -1
if max_q_index < len(q) - 2:
bribe = bribe + 2
q.remove(m)
elif max_q_index < len(q) - 1:
bribe = bribe + 1
q.remove(m)
elif max_q_index == len(q)-1:
q.remove(m)
# no else since max_index < len(q)
更好,但是可以改进。实际上,您有四种情况:
max_q_index == len(q)-1
max_q_index == len(q)-2
max_q_index == len(q)-3
max_q_index < len(q)-3
您应该替换<
来表达这一点。在前三种情况下,您从q
中删除了最大值:
for _ in range(len(q)):
m = max(q)
max_q_index = q.index(max(q)) # position of the max
if max_index < len(q) - 3:
return -1
if max_index == len(q) - 3:
bribe = bribe + 2
elif max_index == len(q) - 2:
bribe = bribe + 1
q.remove(m)
现在,我们了解发生了什么:如果列表几乎已排序,则最大值始终位于最后三个项目中,并且循环遍历q
的每个元素。否则,您会休息。您可以这样写:
for _ in range(len(q)):
m = max(q)
max_q_index = q.index(m) # position of the max
distance = len(q) - 1 - max_q_index
if distance >= 3:
return -1
bribe += distance
q.remove(m)
您想要一个距离的总和,因此遵守规则2,但是控制流使用跳转:找到distance >= 3
后立即返回,并且每次迭代都从q
中删除元素(副作用)。 您不应在此处使用列表理解。
您可以使用其他策略:对值及其索引进行排序:
>>> L = [1,2,4,3,7,5]
>>> list(zip(L, range(len(L))))
[(1, 0), (2, 1), (4, 2), (3, 3), (7, 4), (5, 5)]
>>> S = sorted(zip(L, range(len(L))))
>>> S
[(1, 0), (2, 1), (3, 3), (4, 2), (5, 5), (7, 4)]
函数zip
压缩列表中的元素和数字0、1、2、3、4 ...,即它们在列表中的位置。我们按值对产生的元组进行排序。现在,将元组的第二个值(位置)与元组的当前索引进行比较:如果位置小于或等于索引,则max不是列表的最后一个元素,我们增加了贿赂;如果位置大于索引,则最大值为列表的最大值。
>>> bribe = 0
>>> for i, (_, pos) in enumerate(S):
... distance = max(i - pos, 0)
... if distance >= 3:
... raise Exception() # can't return outside of a function.
... bribe += distance
...
>>> bribe
2
使用L = [1,2,7,3,4,5]
,您将获得一个例外。
如果您不需要distance >= 3
的快捷方式,则可以使用列表理解:
>>> L = [1,2,4,3,7,5]
>>> sum(max(i - pos, 0) for i, (_, pos) in enumerate(sorted(zip(L, range(len(L))))))
2
>>> L = [1,2,7,3,4,5]
>>> sum(max(i - pos, 0) for i, (_, pos) in enumerate(sorted(zip(L, range(len(L))))))
3
可以破解列表理解以引发异常并满足最初的行为,但是不要这样做。