简体   繁体   English

Python:清单,变异,递归问题

[英]Python: lists, mutation, recursion issue

What I'm trying to do is create a final function inbounds that consumes a list of int (values) and two integers lower and upper. 我正在尝试做的是创建一个最终函数入站,该函数使用一个int(值)列表以及两个上下两个整数。 It produces an integer of the total numbers in values that are less than lower and greater than upper. 它产生的整数总数小于和小于上限值。 It also mutates values. 它还会变异值。 If there is an int in values that is less than lower it will mutate that value to lower and is there is an int in values that is greater than upper it will mutate that value to upper. 如果值的int小于lower,它将使该值变为low;如果值的int大于upper,则将其变为upper。 ex: listin=[-3,82,105,86,-10,119,100,70] inbounds (listint, 0, 100) => 4, and v is mutated to [0,82,100,86,0,100,100,70]. 例如:listin = [-3,82,105,86,-10,119,100,70]入站(listint,0,100)=> 4,并且v突变为[0,82,100,86,0,100,100,70]。

So I have tried two things so far: 因此,到目前为止,我已经尝试了两件事:

The first thing I tried is: 我尝试的第一件事是:

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

This does return 4 but the problem with this is that I realized it would only mutate values[0] so then I tried my 2nd attempt to solve this by creating another function that has pos instead of 0 and I add 1 to pos each time it recurses: 这确实返回4,但问题是我意识到它只会使values [0]发生变化,因此我尝试第二次尝试通过创建另一个具有pos而不是0的函数来解决此问题,并且每次将pos加1递归:

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)

Issue with is is that inbounds does nothing!!? 问题是入站什么都不做!? Why? 为什么? I don't get 4 when I test the example and I get the original inlist without any mutations... 当我测试示例时我没有得到4,并且我得到了没有任何变化的原始列表...

edit: Also I tried changing the base case of pos <= len(values) and that still doesn't work 编辑:我也尝试更改pos <= len(values)的基本情况,但这仍然行不通

Problem is in the first condition. 问题是首要条件。 if pos < len(values) should be pos >= len(values) instead. if pos < len(values)应该是pos >= len(values)

Another approach will be to use list comprehensions: 另一种方法是使用列表推导:

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

There were few problems with your second attempt. 第二次尝试几乎没有问题。 Your base-case is wrong - it should be if pos >= len(values) . 您的基本情况是错误的-应该是if pos >= len(values) Also, you were recursing on the wrapper function, not the helper/inside function. 另外,您使用的是包装器功能,而不是辅助/内部功能。 Finally, you need to return the call to your helper function in your wrapper function. 最后,您需要将调用return给包装函数中的辅助函数。 See the following: 请参阅以下内容:

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]

However, in general, recursion is to be avoided in Python. 但是,通常在Python中应避免递归。 Here is a Pythonic way borrowing Marat's clever min(max()) trick: 这是借用Marat的聪明的min(max())技巧的Python方法:

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]

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM