如何使用 repeat、while 循环或其他迭代技术根据某些规则编写 returns 输入向量索引的函数

How to write a function that returns indexes of input vector according to some rules, using repeat, while loop, or other iteration technique

我正在尝试编写一个将数字向量作为输入的函数,并且 return 是输入向量的较短版本的 indexes,根据一些规则:

问题:如果我们在路线(b)中结束,我们可能会遇到所有矢量元素现在都相同的情况。在这种情况下,我们想再次遍历 (a) 以最小化到第一个元素。

例子

假设我想通过我的函数传递以下向量:

my_vec_1 <- c(1, 2, 1, 2, 3)
my_vec_2 <- c(4, 4, 4)
my_vec_3 <- c(1, 2, 1, 4, 1)
my_vec_4 <- c(3, 3, 3, 4) 

还有那个:

special_treatment_value <- 4

根据我的规则,函数应该 return 输出:

我目前的尝试

get_indexes <- function(x, special_val) {
  if (var(x) == 0) { # route (a)
    output_idx <- 1
    return(output_idx)
  }
  
  idx_entire_length <- 1:length(x)
  
  if (any(x == special_val)) { # route (b)
    idx_to_remove <- which(x == special_val)
    output_idx    <- idx_entire_length[-idx_to_remove]
    return(output_idx)
  }
  
  # else
  output_idx <- idx_entire_length # route (c)
  return(output_idx)
}

get_indexes(my_vec_1, 4)
#> [1] 1 2 3 4 5
get_indexes(my_vec_2, 4)
#> [1] 1
get_indexes(my_vec_3, 4)
#> [1] 1 2 3 5
get_indexes(my_vec_4, 4)
#> [1] 1 2 3

我想应该有一些 repeat 块或 while 循环,但我不知道如何正确(有效)地实现它。

您可以在条件 (b) 中重复通过 (a) 的条件,例如:

f <- function(x, treatment){
  if(var(x) == 0) 1 else {
    if(treatment %in% x) {
      x[-which(x == treatment)] |>
        (\(.) if(var(.) == 0) 1 else (1:length(x))[-which(x == treatment)])()
    } else {
      1:length(x)
    }
  }
}

lapply(list(v1, v2, v3, v4), f, 4)

[[1]]
[1] 1 2 3 4 5

[[2]]
[1] 1

[[3]]
[1] 1 2 3 5

[[4]]
[1] 1

你可以试试

foo <- function(x, y){
 
  tmp <- which(x != y) 
  
 if(dplyr::n_distinct(x[x!=y])<=1){
   tmp <- 1
 }
  
 return(tmp) 
}

相反 n_distinct() 你可以使用 length(unique())

结果:

lapply(list(my_vec_1, my_vec_2, my_vec_3, my_vec_4), foo, 4)
[[1]]
[1] 1 2 3 4 5

[[2]]
[1] 1

[[3]]
[1] 1 2 3 5

[[4]]
[1] 1