有没有办法将 Python 转换为 R?

Is there a way to convert Python to R?

嘿,我正在尝试将我的 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]
}

我建议您可以将 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)])
}

你有几个问题。

  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)] 在 R.
  4. R 的range 功能与Python 的range 功能不同。 R 中的等效项是 seqa:b(例如 3:n)。不是说它是右包含的,而 pythons 是右独占的!
  5. 您没有像在 python 中那样将中间结果存储在 a 中。您需要在 运行-time
  6. 时执行此操作

最后一个:R 函数默认 return 最后一个计算。所以没有必要显式使用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]
  }
}

注意 3 件事:

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

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

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

的先前值
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 行代码,因此我做到了。