我怎样才能不重复写类似的代码?
How can I not repeat writing similar code?
我有两个非常相似的函数,除了条件相反之外,几乎是一模一样的。我想遵循 DRY 模式,但我之前在某处读到过,将布尔值传递给函数以改变行为是一种不好的做法(因为它很难维护)。在这里我编写干净且非重复代码的最佳选择是什么?谢谢
def find_upper_tangent(left, right):
l_idx = get_rightmost(left)
r_idx = get_leftmost(right)
upper_tangent_left = False
upper_tangent_right = False
prev_slope = get_slope(left[l_idx], right[r_idx])
while not upper_tangent_left or not upper_tangent_right:
while not upper_tangent_left:
# move counter clockwise
next_slope = get_slope(left[(l_idx - 1) % len(left)], right[r_idx])
if next_slope < prev_slope:
l_idx = (l_idx - 1) % len(left)
prev_slope = next_slope
upper_tangent_right = False
else:
upper_tangent_left = True
while not upper_tangent_right:
# move clockwise
next_slope = get_slope(left[l_idx], right[(r_idx + 1) % len(right)])
if next_slope > prev_slope:
r_idx = (r_idx + 1) % len(right)
prev_slope = next_slope
upper_tangent_left = False
else:
upper_tangent_right = True
return l_idx, r_idx
def find_lower_tangent(left, right):
l_idx = get_rightmost(left)
r_idx = get_leftmost(right)
lower_tangent_left = False
lower_tangent_right = False
prev_slope = get_slope(left[l_idx], right[r_idx])
while not lower_tangent_left or not lower_tangent_right:
while not lower_tangent_left:
# move clockwise
next_slope = get_slope(left[(l_idx + 1) % len(left)], right[r_idx])
if next_slope > prev_slope:
l_idx = (l_idx + 1) % len(left)
prev_slope = next_slope
lower_tangent_right = False
else:
lower_tangent_left = True
while not lower_tangent_right:
# move counter clockwise
next_slope = get_slope(left[l_idx], right[(r_idx - 1) % len(right)])
if next_slope < prev_slope:
r_idx = (r_idx - 1) % len(right)
prev_slope = next_slope
lower_tangent_left = False
else:
lower_tangent_right = True
return l_idx, r_idx
我认为类似的东西应该做同样的计算:
def find_upper_tangent(left, right):
return find_tangent(left, right, -1)
def find_lower_tangent(left, right):
return find_tangent(left, right, 1)
def find_tangent(left, right, shift_val):
l_idx = get_rightmost(left)
r_idx = get_leftmost(right)
prev_slope = get_slope(left[l_idx], right[r_idx])
next_slope = prev_slope
while compare(next_slope, prev_slope) == (shift_val / shift_val):
# move counter clockwise
prev_slope = next_slope
l_idx = (l_idx + shift_val) % len(left)
next_slope = get_slope(left[l_idx], right[r_idx])
while compare(next_slope, prev_slope) == (shift_val / -shift_val)):
# move clockwise
prev_slope = next_slope
r_idx = (r_idx - shift_val) % len(right)
next_slope = get_slope(left[l_idx], right[r_idx])
return l_idx, r_idx
def compare(v1, v2):
return -1 if v1 > v2 else 0 if v1 == v2 else 1
在我看来,这比传递一个标志要好,因为您传递的是一个有意义并用于计算的值。
我是怎么来到这里的
既然你要求的是一种方法,我将尝试描述我是如何找到这个解决方案的:
简化代码
- 外部
while
循环仅 运行 一次,因此可以将其删除。这是关键,因为它消除了循环条件变量的一种使用。
- 然后我们看到每个剩余的
while
循环都有一个 else
子句,它只设置循环条件变量。相反,我们可以简单地使用 if
条件作为循环条件。这消除了布尔变量的需要并减少了代码路径的数量——这两个都是简化代码的伟大目标!
- 现在我们看到我们需要更改操作顺序。在计算新值之前,我们需要保存
next_slope
的值。我们还对新指数进行了两次计算。一次获取斜率,一次保存值。相反,我们可以计算新的索引,然后在斜率计算中使用它。
注意代码中的相似之处
- 请注意,在两个循环中,我们移动了索引,但方向相反。我们可以添加一个移位值参数并编写代码,即使值相同,移位的方向也会改变。
- 注意上下切线计算中左右循环的比较方向不同。为了解决这个问题,我们可以编写一个函数来比较两个事物,returns 如果第一个更大则为 -1,如果第二个更大则为 1,如果它们相同则为 0。
- 现在我们有了移位值,它会根据我们是在寻找上限还是下限而具有不同的符号,我们可以使用它来翻转
while
条件的方向。
我尚未验证此解决方案是否有效 - 如果您想 post 一些测试数据和预期结果,那就太好了!
我有两个非常相似的函数,除了条件相反之外,几乎是一模一样的。我想遵循 DRY 模式,但我之前在某处读到过,将布尔值传递给函数以改变行为是一种不好的做法(因为它很难维护)。在这里我编写干净且非重复代码的最佳选择是什么?谢谢
def find_upper_tangent(left, right):
l_idx = get_rightmost(left)
r_idx = get_leftmost(right)
upper_tangent_left = False
upper_tangent_right = False
prev_slope = get_slope(left[l_idx], right[r_idx])
while not upper_tangent_left or not upper_tangent_right:
while not upper_tangent_left:
# move counter clockwise
next_slope = get_slope(left[(l_idx - 1) % len(left)], right[r_idx])
if next_slope < prev_slope:
l_idx = (l_idx - 1) % len(left)
prev_slope = next_slope
upper_tangent_right = False
else:
upper_tangent_left = True
while not upper_tangent_right:
# move clockwise
next_slope = get_slope(left[l_idx], right[(r_idx + 1) % len(right)])
if next_slope > prev_slope:
r_idx = (r_idx + 1) % len(right)
prev_slope = next_slope
upper_tangent_left = False
else:
upper_tangent_right = True
return l_idx, r_idx
def find_lower_tangent(left, right):
l_idx = get_rightmost(left)
r_idx = get_leftmost(right)
lower_tangent_left = False
lower_tangent_right = False
prev_slope = get_slope(left[l_idx], right[r_idx])
while not lower_tangent_left or not lower_tangent_right:
while not lower_tangent_left:
# move clockwise
next_slope = get_slope(left[(l_idx + 1) % len(left)], right[r_idx])
if next_slope > prev_slope:
l_idx = (l_idx + 1) % len(left)
prev_slope = next_slope
lower_tangent_right = False
else:
lower_tangent_left = True
while not lower_tangent_right:
# move counter clockwise
next_slope = get_slope(left[l_idx], right[(r_idx - 1) % len(right)])
if next_slope < prev_slope:
r_idx = (r_idx - 1) % len(right)
prev_slope = next_slope
lower_tangent_left = False
else:
lower_tangent_right = True
return l_idx, r_idx
我认为类似的东西应该做同样的计算:
def find_upper_tangent(left, right):
return find_tangent(left, right, -1)
def find_lower_tangent(left, right):
return find_tangent(left, right, 1)
def find_tangent(left, right, shift_val):
l_idx = get_rightmost(left)
r_idx = get_leftmost(right)
prev_slope = get_slope(left[l_idx], right[r_idx])
next_slope = prev_slope
while compare(next_slope, prev_slope) == (shift_val / shift_val):
# move counter clockwise
prev_slope = next_slope
l_idx = (l_idx + shift_val) % len(left)
next_slope = get_slope(left[l_idx], right[r_idx])
while compare(next_slope, prev_slope) == (shift_val / -shift_val)):
# move clockwise
prev_slope = next_slope
r_idx = (r_idx - shift_val) % len(right)
next_slope = get_slope(left[l_idx], right[r_idx])
return l_idx, r_idx
def compare(v1, v2):
return -1 if v1 > v2 else 0 if v1 == v2 else 1
在我看来,这比传递一个标志要好,因为您传递的是一个有意义并用于计算的值。
我是怎么来到这里的
既然你要求的是一种方法,我将尝试描述我是如何找到这个解决方案的:
简化代码
- 外部
while
循环仅 运行 一次,因此可以将其删除。这是关键,因为它消除了循环条件变量的一种使用。 - 然后我们看到每个剩余的
while
循环都有一个else
子句,它只设置循环条件变量。相反,我们可以简单地使用if
条件作为循环条件。这消除了布尔变量的需要并减少了代码路径的数量——这两个都是简化代码的伟大目标! - 现在我们看到我们需要更改操作顺序。在计算新值之前,我们需要保存
next_slope
的值。我们还对新指数进行了两次计算。一次获取斜率,一次保存值。相反,我们可以计算新的索引,然后在斜率计算中使用它。
- 外部
注意代码中的相似之处
- 请注意,在两个循环中,我们移动了索引,但方向相反。我们可以添加一个移位值参数并编写代码,即使值相同,移位的方向也会改变。
- 注意上下切线计算中左右循环的比较方向不同。为了解决这个问题,我们可以编写一个函数来比较两个事物,returns 如果第一个更大则为 -1,如果第二个更大则为 1,如果它们相同则为 0。
- 现在我们有了移位值,它会根据我们是在寻找上限还是下限而具有不同的符号,我们可以使用它来翻转
while
条件的方向。
我尚未验证此解决方案是否有效 - 如果您想 post 一些测试数据和预期结果,那就太好了!