在 Shiny 应用程序中,如何暂停 for 循环以获取用户输入,然后在单击按钮后继续?

Posted

技术标签:

【中文标题】在 Shiny 应用程序中,如何暂停 for 循环以获取用户输入,然后在单击按钮后继续?【英文标题】:In a Shiny app, how can I pause a for loop to grab a user input, then continue after a button click? 【发布时间】:2019-11-13 12:03:49 【问题描述】:

我正在编写一个闪亮的应用程序来模拟各种草稿,用户将从模拟选择之间的列表中进行选择(随机选择)。为了更好地解释这个前提,我们从 12 个选项的列表开始。当他们的“槽”出现时,用户将选择这些选项之一。因此,如果他们选择“4”作为他们的位置,前 3 个选项将被随机模拟。然后用户将做出他们的选择,最后的 8 个选择将被随机模拟……无论何时做出选择,该选择都会从列表中删除。所以每个选项只能选择一次。

所以我需要遍历数字 1-12,然​​后随机模拟该选择,或者(如果轮到用户)允许通过用户输入进行选择。

我还没有弄清楚如何在用户做出选择之前暂停循环,然后在单击按钮确认后继续。我的最小、可重现示例的代码如下。照原样,用户基本上被跳过了,因为循环没有暂停。

new_list<-c()

choice_list<-c("Choice 1","Choice 2","Choice 3","Choice 4",
               "Choice 5","Choice 6","Choice 7","Choice 8",
               "Choice 9","Choice 10","Choice 11","Choice 12")

ui<-navbarPage(title="Title", id="navbar",
  tabPanel("Main",
    selectInput(inputId="slot", label="Select your Slot", choices=1:12),
    actionButton(inputId="start", label="Start Process"),
    fluidRow(hr()),
    selectInput(inputId="user_choice", label="Choose an Option", choices=choice_list),
    actionButton(inputId="selection", label="Make Selection"))
)

server<-function(input, output, session) 
  observeEvent(input$start, 
    user_slot<-isolate(input$slot)
    print(paste0("User slot: ",user_slot))
    print("----------")
    print("----------")
    for (i in 1:12) 
      if (i==user_slot) 
        print("TIME FOR USER SELECTION")
        observeEvent(input$selection, 
          user_choice<-isolate(input$user_choice)
          print(paste0("User choice: ",user_choice))
          new_list<-c(new_list,user_choice)
          choice_list<-choice_list[choice_list!=user_choice]
        )
       else 
        random_number<-sample(seq(1:length(choice_list)),1)
        print(paste0("Random number: ",random_number))
        random_choice<-choice_list[random_number]
        print(paste0("Random choice: ",random_choice))
        new_list<-c(new_list,random_choice)
        choice_list<-choice_list[choice_list!=random_choice]
      
      print(paste0("# of choices left: ",length(choice_list)))
      print("----------")
    
  )


shinyApp(ui=ui, server=server)

有没有办法暂停循环,但在触发“observeEvent()”时让它继续?是否有可以解决此问题的“observeEvent()”替代方法?还是我必须重新设计具有不同循环过程的解决方案?

提前致谢!

【问题讨论】:

【参考方案1】:

我认为您在循环中无法观察到事件,我遇到了完全相同的问题,并尝试使用 Sys.sleep() 和 while 循环暂停它,等待用户输入会更改值以中断循环但它不起作用。

我认为最简单的解决方案是将代码分成几个部分:循环所在的函数,当它是用户的插槽时,循环中断并且函数返回剩余的选择数量。当用户选择他的选项时,循环会重新开始,剩余的选项数量。

server<-function(input, output, session) 
  values <- reactiveValues(
    n = 12
  )

  observeEvent(input$selection, 
    user_choice<-isolate(input$user_choice)
    print(paste0("User choice: ",user_choice))
    new_list<-c(new_list,user_choice)
    choice_list<<-choice_list[choice_list!=user_choice]
    print(paste0("# of choices left: ",length(choice_list)))
    print("----------")

    loop(0, values$n)

  )

  observeEvent(input$start, 
    user_slot<-isolate(input$slot)
    print(paste0("User slot: ",user_slot))
    print("----------")
    print("----------")

    values$n <- loop(user_slot)
  )


loop <- function(user_slot, n = 12)
  for (i in 1:n) 
    if (i==user_slot) 
      print("TIME FOR USER SELECTION")
      break
     else 
      random_number<-sample(seq(1:length(choice_list)),1)
      print(paste0("Random number: ",random_number))
      random_choice<-choice_list[random_number]
      print(paste0("Random choice: ",random_choice))
      new_list<-c(new_list,random_choice)
      choice_list<<-choice_list[choice_list!=random_choice]
    
    print(paste0("# of choices left: ",length(choice_list)))
    print("----------")
  
  return(n-i)

如果您找到其他解决方案,请告诉我

【讨论】:

看看这是否有帮助:***.com/questions/49452857/… 在这种情况下,我们有一个包含 10 个选项的列表。我们随机选择两个并向用户呈现这两个选项。用户选择其中之一,未选择的将被删除。我们保留用户的选择,并从剩余的 8 个选项中随机选择另外 1 个。我不确定这是否正是您想要的,但也许它可以给您一些想法。

以上是关于在 Shiny 应用程序中,如何暂停 for 循环以获取用户输入,然后在单击按钮后继续?的主要内容,如果未能解决你的问题,请参考以下文章

如何在 for 循环中暂停

在 Activity 内部,如何暂停 for 循环以调用片段,然后在按钮单击片段后恢复循环以重新开始

For 循环:如何在 100 次循环后暂停 x 秒? [复制]

如何在DispatcherTimer结束之前暂停for循环?

点击Shiny App中每次迭代中的多个图

如何使 tabItem 仪表板中的 for 循环或 lapply 循环中的函数闪亮