我写了一个函数,它取一个学位并返回方向为' N' NE' NE'等等。非常简单,但它很难看 - 是否有任何方法可以重写它以使它更漂亮?
def orientation(tn):
if 23 <= tn <= 67:
o = 'NE'
elif 68 <= tn <= 113:
o = 'E'
elif 114 <= tn <= 158:
o = 'SE'
elif 159 <= tn <= 203:
o = 'S'
elif 204 <= tn <= 248:
o = 'SW'
elif 249 <= tn <= 293:
o = 'W'
elif 294 <= tn <= 338:
o = 'NW'
else:
o = 'N'
return o
答案 0 :(得分:18)
使用bisection:
from bisect import bisect_left
directions = ['N', 'NE', 'E', 'SE', 'S', 'SW', 'W', 'NW', 'N']
boundaries = [22, 67, 113, 158, 203, 248, 293, 338, 360]
def orientation(tn):
return directions[bisect_left(boundaries, tn)]
bisect_left()
(非常有效)找到您将tn
插入boundaries
列表的索引;然后将该索引映射到directions
列表以转换为字符串。
Bisection最多只需4个步骤即可找到正确的边界(log2(len(boundaries))
)。
您还可以添加22并将模数值除以模数360:
directions = ['N', 'NE', 'E', 'SE', 'S', 'SW', 'W', 'NW', 'N']
def orientation(tn):
index = ((tn + 22) % 360) // 45
return directions[index]
然而,您的原始边界不是均匀分布在每个45度,因此结果略有不同(您的N
边界跨度为44度,而E
分配为46度)。 Bisection并不关心这些例外情况;你可以随心所欲地改变边界。
答案 1 :(得分:6)
您可以将整数索引计算到指南针方向列表中:
def compass(angle):
return ['N', 'NE', 'E', 'SE', 'S', 'SW', 'W', 'NW', 'N'][int(8*(angle+22.)/360)]
答案 2 :(得分:4)
尝试将整数除以45并按此数字(索引)寻址数组成员。该数组应包含方向。
答案 3 :(得分:1)
相同的原则,但更清晰的imo,改为使用ternary operator:
def orientation(tn):
tn = mod(tn, 360)
return "N" if tn < 23 else \
"NE" if tn < 68 else \
"E" if tn < 114 else \
"SE" if tn < 159 else \
"S" if tn < 204 else \
"SW" if tn < 249 else \
"W" if tn < 294 else \
"NW" if tn < 339 else \
"N"
显然,这种方法并不适用于其他场景,但就个人而言,对于您的特定问题,我实际上更喜欢这个而不是更通用的替代方案,因为它是简单,清晰,可读,简单的代码:任何登陆此定义的人都会知道无论编程技巧如何,它都会在眨眼之间完成它的作用。 :P