简体   繁体   中英

R vector staying the same length after indexing within recursive function

I wrote a recursive binary search function in R which finds the smallest element in a vector that is greater than a given value:

binary_next_biggest <- function(x, vec){
  if (length(vec) == 1){
    if (x < vec[1]){
      return(vec[1])
    } else {
      return(NA)
    }
  } else {
    mid = ceiling(length(vec)/2)
    if (x < vec[mid]){
      return(binary_next_biggest(x, vec[1:mid]))
    } else {
      return(binary_next_biggest(x, vec[mid+1:length(vec)]))
    }
  }
}

I've written this exact same function in Python with no issues (code below), but in R it does not work.

import numpy as np

def binary_next_biggest(x, arr):
    if len(arr)==1:
        if x < arr[0]:
            return arr[0]
        else:
            return None
    else:
        mid = int(np.ceil(len(arr)/2)-1)
        if x < arr[mid]:
            return binary_next_biggest(x, arr[:mid+1])
        else:
            return binary_next_biggest(x, arr[mid+1:])

Through debugging in RStudio I discovered the mechanics of why it's not working: indexing the vector in my above function is returning a vector of the same length, so that if

vec <- 1:10

and vec is indexed within the function,

vec[6:10]

the resulting vector passed to the new call of binary_next_biggest() is

6 7 8 9 10 NA NA NA NA NA

where I would expect

6 7 8 9 10

What's going on here? I know I can just rewrite it as a while loop iteratively changing indexes, but I don't understand why vector indexing is behaving this way in the code I've written. Within the interactive R console indexing behaves as expected and changes the vector length, so why would it behave differently within a function, and what would be the appropriate way to index for what I'm trying to do?

The cause of the strange behavior of the code is an error in indexing of the vector elements. The part mid+1:length(vec) should be (mid+1):length(vec) because the : operator is executed before addition.

Here is an illustration of the difference.

5 + 1:10
# [1]  6  7  8  9 10 11 12 13 14 15
(5+1):10
# [1]  6  7  8  9 10

There might be a reason why you're doing a binary search (simplified example of more complicated problem?), but there are easier ways to do this in R.

vec <- 1:1000
x <- 49
min(vec[which(vec > x)])
# [1] 50

Which works even if vec isn't ordered.

vec <- sample.int(1000)
min(vec[which(vec > x)])
# [1] 50

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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