Python递归与迭代

时间:2016-09-12 18:01:52

标签: python recursion iteration

我无法在代码中找到错误。它在我的cmd上运行得很好但是没有通过实验室平台测试。这是一个问题:

  

你需要分别设计一个名为replicate_iter和replicate_recur的迭代和递归函数,它将接收两个参数:times是重复的次数,data是要重复的数字或字符串。

该函数应该返回一个包含data参数重复的数组。例如,replicate_recur(3, 5)replicate_iter(3,5)应返回[5,5,5]。如果times参数为负或零,则返回一个空数组。如果参数无效,请引发ValueError。"

现在这是我的代码:

my_list1 = []
my_list2 = []
   def replicate_iter(times,data):
      try:
        if type(data) != int and type(data) != str:
          raise ValueError('Invalid Argument')
        times += 0
          if times > 0:
            x = 0
            while x < times:
            my_list2.append(data)
            x = x+1
           return my_list2
         else:
          return []
    except (ValueError,AttributeError,TypeError):
        raise ValueError('Invalid Argument')

def replicate_recur(times,data):
    try:
        if type(data) != int and type(data) != str:
          raise ValueError('Invalid Argument')
        times += 0
        if times <= 0:
          return my_list1
        else:
          my_list1.append(data)
          return replicate_recur(times-1,data)
    except(AttributeError,TypeError):
        raise ValueError('Invalid Argument')

8 个答案:

答案 0 :(得分:4)

这有效!

def replicate_iter(times, data):
    if((not isinstance(times, int)) or (not isinstance(data, (int, float, long, complex, str)))):
            raise ValueError("Invalid arguments")
    elif(times <= 0):
            return []
    else:
            array = []
            for x in range(times):
                    array.append(data)
            return array


def replicate_recur(times, data):
    if((not isinstance(times, int)) or (not isinstance(data, (int, float, long, complex, str)))):
            raise ValueError("Invalid arguments")
    elif(times <= 0):
            return []
    else:
            return ([data] + replicate_recur((times - 1), data))        

答案 1 :(得分:1)

def replicate(c,times):
    return [c]*times

def replicate2(c,times):
    return [c for i in range(times)]

def replicate3(c,times):
    result = []
    for i in range(times): result.append(c)
    return result

def replicate4(c,times):
    return [c] + (replicate4(c,times-1) if times > 0 else [])

答案 2 :(得分:1)

两者的基本实现(虽然说实话并不是好Python):

def replicate_iter(times, data):
    result = []
    for _ in range(times):  # xrange in Python2
        result.append(data)
    return result


def replicate_recur(times, data):
    if times <= 0:
        return []
    return [data] + replicate_recur(times - 1, data)


assert replicate_iter(3, 5) == [5, 5, 5]
assert replicate_recur(3, 5) == [5, 5, 5]
assert replicate_iter(4, "abc") == ["abc", "abc", "abc", "abc"]
assert replicate_recur(4, "abc") == ["abc", "abc", "abc", "abc"]

它们简单明了,并且显示了两种方法之间的基本差异。

Pythonic代码将使用乘以序列或列表理解:

result = [data for _ in range(times)]
result = [data] * times

在任何生产代码中,递归都不会真正用于此任务。

答案 3 :(得分:1)

我认为你的代码比其他人说的更接近正确 - 你只需要重新安排一些元素:

def replicate_iter(times, data):
    if type(data) != int and type(data) != str:
        raise TypeError('Invalid Argument')

    try:
        my_list = []

        if times > 0:
            for _ in range(times):
                my_list.append(data)

        return my_list

    except (ValueError, TypeError):
        raise ValueError('Invalid Argument') from None

def replicate_recur(times, data):
    if type(data) != int and type(data) != str:
        raise TypeError('Invalid Argument')

    try:
        my_list = []

        if times > 0:
            my_list.append(data)
            my_list.extend(replicate_recur(times - 1, data))

        return my_list

    except (ValueError, TypeError):
        raise ValueError('Invalid Argument') from None

我同意错误处理有点复杂,但这是规范所要求的。虽然具体关于times参数,但如果data不是可接受的类型之一,则规范对于生成哪个错误是模棱两可的,但TypeError似乎有意义。

答案 4 :(得分:1)

对于递归版本我推荐tail recursion正如你所做的那样,其他例子即使最简单的使用列表连接(+),它产生一个新列表,其中包含每个元素的副本,当您可以传递单个列表时,如同使用迭代版本一样添加元素时,这会浪费太多的时间和空间

这是一个例子

def replicate_recur(times, data, result=None):
    if result is None:
        result = []
    if times <= 0 :
        return result
    else:
        result.append(data)
        return replicate_recur(times-1,data,result)

此外,您可以避免使用辅助功能

反复重复检查
def replicate_recur_aux(times, data, result):
    if times <= 0 :
        return result
    else:
        result.append(data)
        return replicate_recur_aux(times-1,data,result)  

def replicate_recur(times, data):
    if not isinstance(data, int) and not isinstance(data, str):
        raise ValueError('Invalid Argument')
    return replicate_recur_aux(times,data,[])

这样主要功能就可以完成所有需要完成的检查和所有必要的设置,这样辅助功能就可以完成工作而不用担心或不必要地检查同一件事。

对于迭代版本,任何其他示例都很好,但也许你的老师想要这样的东西

def replicate_iter(times, data):
    if not isinstance(data, int) and not isinstance(data, str):
        raise ValueError('Invalid Argument')
    result = []
    if times <=0:
        return result
    for i in range(times):
        result.append(data)
    return result

现在注意两个版本之间的相似性,你可以轻松地将一个版本转换为另一个版本

答案 5 :(得分:1)

我认为迭代版本很简单,其他人提供了很好的答案。至于递归,我总是想看看我是否可以提出分而治之的策略,而不是一次一步地减少问题,以避免炸掉堆栈。以下是:

def replicate_recur(times, data):
    def f(n, value):
        if n < 1:
            return [] 
        result = f(n // 2, value) * 2
        if n % 2 > 0:
            result += [value] 
        return result

    if not isinstance(data, int) and not isinstance(data, str):
        raise ValueError('Must be int or str')
    return f(times, data)

这使用内部递归函数f()来避免重复data的类型检查。递归构造了一半大小的列表,并将其加倍(如果当前n为偶数)或将其加倍并再添加一次data(如果当前n为单数)。

尝试一下,你会喜欢它!

答案 6 :(得分:1)

我尝试了这个,它适用于那个测试!

def replicate_iter(times,data):
    Array = []
    if type(times) != int or not isinstance(data, (int, float, complex, str)):
        raise ValueError ('Invalid Value')
    elif times < 0:
        return []
    else:
        for x in range (times):
            Array.append(data)
        return Array


def replicate_recur(times,data):
    Array = []
    if type(times) != int or not isinstance(data, (int, float, complex, str)):
        raise ValueError ('Invalid Value')
    elif times <= 0:
        return []
    else:
       Array = replicate_recur(times-1,data)
       Array.append(data)
    return Array

答案 7 :(得分:0)

def replicate_iter(times, data):
    if not isinstance(data, int) and not isinstance(data, str):
        raise ValueError('Must be int or str')
    if times <= 0:
        return []
    return [data for _ in range(times)]

def replicate_recur(times, data):
    if not isinstance(data, int) and not isinstance(data, str):
        raise ValueError('Must be int or str')
    if times <= 0:
        return []
    return [data] + replicate_recur(times-1, data)

输出

>>> replicate_iter(3, 5)
[5, 5, 5]

>>> replicate_recur(3, 5)
[5, 5, 5]

边缘情况

>>> replicate_iter(0, 5)
[]

>>> replicate_iter(3, list())
Traceback (most recent call last):
  File "<pyshell#2>", line 1, in <module>
    replicate_iter(3, list())
  File "C:/temp/temp.py", line 3, in replicate_iter
    raise ValueError('Must be int or str')
ValueError: Must be int or str