【问题标题】:Python: lists, mutation, recursion issuePython:列表、变异、递归问题
【发布时间】:2017-06-24 03:14:36
【问题描述】:

我要做的是创建一个最终函数 inbounds,它使用一个 int(值)列表和两个整数 lower 和 upper。它产生小于小于和大于上值的总数的整数。它还会改变值。如果值中有一个小于 lower 的 int 值,它将将该值更改为 lower 并且如果值中有一个大于 upper 的 int 值,它将将该值更改为 upper。 例如:listin=[-3,82,105,86,-10,119,100,70] inbounds (listint, 0, 100) => 4,并且 v 变为 [0,82,100,86,0,100,100,70]。

所以到目前为止我已经尝试了两件事:

我尝试的第一件事是:

def inbounds(values, lower, upper):
    if values == []:
        return 0
    elif lower <= values[0] <= upper:
        return inbounds(values[1:], lower, upper)
    elif lower > values[0]:
        values[0] = lower
        return inbounds(values[1:], lower, upper) + 1
    else:
        values[0] = upper
        return inbounds(values[1:],lower, upper) + 1

这确实返回 4,但问题是我意识到它只会改变 values[0] 所以我尝试第二次尝试通过创建另一个具有 pos 而不是 0 的函数来解决这个问题,并将 1 添加到 pos每次递归:

def inbounds_from(values, lower, upper, pos):
    if pos < len(values):
        return 0
    elif lower <= values[pos] <= upper:
        return inbounds(values, lower, upper, pos+1)
    elif lower > values[pos]:
        values[pos] = lower
        return inbounds(values, lower, upper, pos+1) + 1
    else:
        values[pos] = upper
        return inbounds(values,lower, upper, pos+1) + 1    

def inbounds(values, lower, upper):
    inbounds_from(values, lower, upper, 0)

问题是入站什么都不做!!?为什么?当我测试示例时我没有得到 4 并且我得到了没有任何突变的原始 inlist...

编辑:我也尝试更改 pos

【问题讨论】:

  • 您将列表的切片传递给每个递归调用,这将返回原始列表的副本。您不会在原始列表中看到任何更改。尝试使用迭代,这是 Python 的方式,或者如果你必须使用递归,尝试传递当前索引并递增你的基本情况为 index == len(values)
  • 抱歉,没有看到您已经尝试过这样做。问题可能是您的包装函数中缺少 return 。它应该是对原版的变异,但我远离我的电脑,目前无法摆弄它。
  • 啊。你的基本情况是错误的。它永远不会超过 if' 块,因为如果您想从索引 0 开始并向上计数,它应该是 if pos &gt;= len(values)...
  • @juanpa.arrivillaga 我试过了,但不幸的是仍然得到相同的结果。

标签: python list recursion mutation


【解决方案1】:

问题在于第一个条件。 if pos &lt; len(values) 应该改为 pos &gt;= len(values)

另一种方法是使用列表推导:

count = sum(upper <= v <= lower for v in values)
values = [min(upper, max(v, lower)) for v in values]  # mutate

【讨论】:

  • 我试过 pos
  • 这在技术上不会改变values。你需要values[:] = [&lt;comprehension]
【解决方案2】:

您的第二次尝试几乎没有问题。你的基本情况是错误的 - 它应该是if pos &gt;= len(values)。此外,您递归的是 wrapper 函数,而不是 helper/inside 函数。最后,您需要 return 在您的包装函数中调用您的辅助函数。请参阅以下内容:

In [4]: def inbounds_from(values, lower, upper, pos):
   ...:     if pos >= len(values):
   ...:         return 0
   ...:     elif lower <= values[pos] <= upper:
   ...:         return inbounds_from(values, lower, upper, pos+1)
   ...:     elif lower > values[pos]:
   ...:         values[pos] = lower
   ...:         return inbounds_from(values, lower, upper, pos+1) + 1
   ...:     else:
   ...:         values[pos] = upper
   ...:         return inbounds_from(values,lower, upper, pos+1) + 1
   ...:
   ...: def inbounds(values, lower, upper):
   ...:     return inbounds_from(values, lower, upper, 0)
   ...:

In [5]: test = [-3,82,105,86,-10,119,100,70]

In [6]: inbounds(test, 0, 100)
Out[6]: 4

In [7]: test
Out[7]: [0, 82, 100, 86, 0, 100, 100, 70]

但是,一般来说,Python 中要避免递归。这是借用 Marat 巧妙的 min(max()) 技巧的 Pythonic 方式:

In [8]: def in_bounds_iter(values, lower, upper):
   ...:     count = 0
   ...:     for i, val in enumerate(values):
   ...:         if not(lower <=  val <= upper):
   ...:             count += 1
   ...:             values[i] = min(upper, max(val, lower))
   ...:     return count
   ...:

In [9]: test = [-3,82,105,86,-10,119,100,70]

In [10]: in_bounds_iter(test, 0, 100)
Out[10]: 4

In [11]: test
Out[11]: [0, 82, 100, 86, 0, 100, 100, 70]

【讨论】:

  • 非常感谢您的帮助和解释!我不知道我是如何错过了对包装器函数的递归,而不是帮助器......并且在包装器上添加 return 很有意义!
猜你喜欢
  • 2020-05-25
  • 1970-01-01
  • 2021-09-22
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多