【问题标题】:Is there a way to convert Python to R?有没有办法将 Python 转换为 R?
【发布时间】:2021-05-15 17:11:47
【问题描述】:

嘿,我正在尝试将我的 python 代码转换为 R,但似乎无法弄清楚递归的最后一部分。如果有两种语言经验的人可以提供帮助,那就太好了!

def robber(nums):
    if len(nums) == 0: return 0
    elif len(nums) <= 2: return max(nums)
    else:
        A = [nums[0], max(nums[0:2])]
        for i in range(2, len(nums)):
            A.append(max(A[i-1], A[i-2] + nums[i]))
    return A[-1]

以上是 Python 版本,以下是我目前尝试转换为 R

robbing <- function(nums) {
    if (length(nums) == 0){
        result <- 0      
    }
    else if(length(nums) <= 2){
        result <- max(nums)     
    }
    else{
      a <- list(nums[0], max(nums(0:2)))
      for (i in range(2, length(nums))){
          result <- max(a[i-1], a[i-2] + nums[i])
      }
    }
    #result <- a[-1]
}

【问题讨论】:

  • 从您的代码中我可以看出,您剩下的问题是如何引用A 的最后一个元素。这应该是一个微不足道的查找。同样,重新配置逻辑以便仅在前面的子句失败时分配该值,是一个简单的else if / else 添加。我错过了什么问题?
  • nums(0:2) 应该是nums[0:2] 的子集,而不是尝试调用名为nums 的函数。此外,R 是 1-indexed 并且具有包容性端点,因此您可能需要检查 nums[0:2] 不是 nums[1:2] (也许?)。我怀疑a &lt;- list(... 也应该是a &lt;- c(...。您的函数目前也不返回任何内容。您需要添加类似于 python 的 return(...) 语句,尽管如果您只输入例如 R 隐式返回一个对象。 max(nums) 作为最后一行,没有分配 &lt;-
  • 能否分享dput(nums)来测试功能?

标签: python r converters


【解决方案1】:

我建议你可以将result改为return()并在函数外重命名对象a,也可以在函数结束时将len改为length()

a <- list(nums[0], max(nums(0:2)))

robbing <- function(nums) {
  if (length(nums) == 0){
    return(0)    
  }
  else if(length(nums) <= 2){
    return(max(nums))     
  }
  else{
    
    for (i in range(2, length(nums))){
      return(max(a[i-1], a[i-2] + nums[i]))
    }
  }
  return(a[length(a)])
}

【讨论】:

  • 嗨@AlvaroMartinez,您的答案有几点提示:a 应存储在函数robbing 中,range 应替换为seqa:b。此外,for 循环不应在每次迭代中 return 以符合问题中的 python 版本。 :-)
【解决方案2】:

你有几个问题。

  1. 您正在对向量进行零索引。 R 是 1 索引的(y 的第一个元素是 y[1] 而不是 y[0]
  2. R 中的范围(python 中的切片)包含。例如:0:2 = c(0, 1, 2) 而python 是右排他的0:2 = [0, 1]
  3. R 使用减号元素“移除”向量的元素,而 Python 使用这些元素从逆序中提取。例如:y[-1] = y[2:length(y)] in R.
  4. R 的 range 函数与 Python 的 range 函数不同。 R 中的等价物将是 seqa:b(例如 3:n)。不是说它是右包含的,而 python 是右排的!
  5. 您没有像在 python 中那样将中间结果存储在 a 中。您需要在运行时执行此操作

最后一个:R 函数默认返回最后一个求值。所以不需要显式使用return。这不是问题,而是可以使代码看起来更干净(或在某些情况下不太干净)的东西。因此,解决您的问题的一种选择是:

robber <- function(nums){
  n <- length(nums) # <= Only compute length **once** =>
  if(n == 0)
    0 # <= Returned because no more code is run after this =>
  else if(n <= 2)
    max(nums) # <= Returned because no more code is run after this =>
  else{
    a <- numeric(n) # <= pre-allocate our vector =>
    a[1:2] <- cummax(nums[1:2]) # <= Cummax instead of c(nums[1], max(nums[1:2])) =>
    for(i in 3:n){ # <= Note that we start at 3, because of R's 1-indexing =>
      a[i] <- max(a[i - 1], a[i - 2] + nums[i])
    }
    a[n]
  }
}

注意三件事:

  1. 我使用 R 向量是 1 索引的,因此我的范围从 3 开始。
  2. 我预先分配了我的a 向量(这里使用numeric(n))。 R 向量扩展,而 python 列表的时间复杂度是恒定的。因此,预分配是在所有情况下都推荐的方式。
  3. 我提取我的长度一次并将其存储在一个变量中。 n &lt;- length(nums)。本质上没有必要多次评估,建议将这些中间结果存储在一个变量中。这适用于任何语言,例如 R、Python,甚至是 C++ 等编译语言(而对于后者,在许多情况下,编译器足够聪明,不会重新计算结果)。

最后我尽可能使用cummax。我觉得有一种优化的方法可以使用矢量化几乎立即获得结果,但我看不出来。

【讨论】:

  • 非常感谢,您的解释帮了大忙。我很少使用 r,所以当我的朋友让我为他转换它时,我很挣扎,需要一些建议。
  • 我的荣幸。很高兴我能帮助你。如果答案回答了您的问题,请确保通过单击投票按钮下方的复选标记将答案标记为“答案”。 :-)
【解决方案3】:

我会避免使用列表。因为附加列表很慢。 (特别是在 R 中!- 向量要好得多。但我们不需要任何序列和索引,如果我们使用像我在这里展示的那样的变量)。 你不需要建立一个列表。 您需要记住的只是前一个 以及 res 的 preprevious 值。

def robber(nums, res=0, prev=0, preprev=0): # local vars predefined here
    for x in nums:
        prev, preprev = res, prev
        res = max(prev, preprev + x)
    return res

这个 python 函数和你给定的一样。 (试试看!)。

在 R 中,这将是:

robber <- function(nums, res=0, prev=0, preprev=0) {
  for (x in nums) {
    preprev <- prev
    prev <- res       # correct order important!
    res <- max(prev, preprev + x)
  }
  res
}

将局部变量定义放入参数列表中节省了 R 3 行代码,因此我做到了。

【讨论】:

    猜你喜欢
    • 2011-06-26
    • 1970-01-01
    • 2014-11-06
    • 2017-03-25
    • 2021-09-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多