Ограничить рекурсивную функцию на основе количества завершенных рекурсий

#r #lapply

#r #lapply

Вопрос:

У меня есть рекурсивная функция, которая извлекает данные из базы данных. База данных огромна, рекурсия занимает некоторое время и в конечном итоге заканчивается ошибкой, поскольку я превысил стек. Я пытаюсь отладить функцию, поэтому я хотел бы ограничить рекурсию, чтобы я мог просмотреть результат до возникновения ошибки стека.

Вот функция. Как я могу установить для нее ограничение рекурсии? ( df$relatedIdEx это просто символьная строка из фрейма данных, которая используется в качестве строки для поиска нового фрейма данных). Если строка уже была просмотрена, то она пропускается — это делается для предотвращения бесконечных циклов

 get_all_dfs <- function(df) {
  lapply(df$relatedIdEx, function(elem) {
    if (as.character(unlist(elem)) %in% already_lookedup) {
      print(paste("Already looked up ",elem," and skipping!"))
      return (NULL)
    } else {
      already_lookedup <<- c(already_lookedup,as.character(unlist(elem)))
    }
    next_df <- myGIConcepts(elem)

    #next_df_list<-list(next_df,my_env)
    if (nrow(next_df)>1) {
      get_all_dfs(next_df)
    } else {
      thelist<-df
    }
  })
}
  

Комментарии:

1. Я думаю, if (as.character(unlist(elem)) %in% already_lookedup) может возникнуть проблема, если длина больше 1. кроме того, для обновления на каждой итерации for цикл был бы лучше

2. sys.nframe() предоставит вам глубину текущего стека вызовов, если это то, что вы хотите ограничить напрямую.

Ответ №1:

Вы можете передать счетчик функции, которая немного более понятна, например get_all_dfs <- function(df,counter) . Но ваш вопрос подразумевает, что подойдет быстрое решение. Счетчик добавляется следующим образом. Обратите внимание, что вы также можете переместить ее в пределах lapply, потенциально, в зависимости от того, где вы хотите разместить счетчик или где его прервать.

 counter <- 0
get_all_dfs <- function(df) {
  counter <<- counter 1
  if (counter > 100) return (NULL)

  lapply(df$relatedIdEx, function(elem) {
    if (as.character(unlist(elem)) %in% already_lookedup) {
      print(paste("Already looked up ",elem," and skipping!"))
      return (NULL)
    } else {
      already_lookedup <<- c(already_lookedup,as.character(unlist(elem)))
    }
    next_df <- myGIConcepts(elem)

    #next_df_list<-list(next_df,my_env)
    if (nrow(next_df)>1) {
      get_all_dfs(next_df)
    } else {
      thelist<-df
    }
  })
}