将递归函数应用于嵌套列表,同时保留子列表的类

Apply a recursive function to a nested list while preserving the classes of sublists

提问人:user51462 提问时间:10/5/2019 最后编辑:ismirsehregaluser51462 更新时间:11/22/2023 访问量:208

问:

我有一个嵌套列表,叫做:inputs

library(htmltools)
library(shiny)

inputs = tagList(
  selectInput('first', 'FIRST', letters), 
  checkboxInput('second', 'SECOND')
)

str(inputs, max.level = 1)
List of 2
 $ :List of 3
  ..- attr(*, "class")= chr "shiny.tag"
  ..- attr(*, "html_dependencies")=List of 1
 $ :List of 3
  ..- attr(*, "class")= chr "shiny.tag"
 - attr(*, "class")= chr [1:2] "shiny.tag.list" "list"

我想修改所有具有类且其元素相等的子列表(请参阅此类子列表的示例),但在这样做时保留列表的原始结构。shiny.tagnamelabelinputs[[1]][["children"]][[1]]

为此,我定义了一个递归函数:hideLabel

hideLabel <- function(tag.list) {

  lapply(tag.list, function(x) {

    if(inherits(x, 'shiny.tag')) {

      if(x$name == 'label') {

        tagAppendAttributes(x, style = 'display:none;')

      } else {

        hideLabel(x$children)

      }

    } else {

      return(x)

    }
  })
} 

以下是将 hideLabel 应用于输入列表的输出:

res = hideLabel(inputs)

str(res, max.level = 1)
List of 2
 $ :List of 2
 $ :List of 1

如上所示,hideLabel 不会返回与原始列表输入结构相同的列表(将第一个代码块中 str 的输出与上面第三个块中 str 的输出进行比较)。我想知道是否有人可以帮助我理解为什么该函数会这样做以及如何修改它?我曾多次尝试重写它,但无济于事。

更新:

在考虑了函数在每个阶段返回的内容后,我让它工作。以下是更新后的函数:

hideLabel <- function(x) {

  children = x$children

  x$children = lapply(children, function(y) {

    if(inherits(y, 'shiny.tag')) {

      if(y$name == 'label') tagAppendAttributes(y, style = 'display:none;') else hil(y)

    } else y

  })

  return(x)

}

这将保留原始列表的结构:

inputs_new = lapply(inputs, hideLabel)

str(inputs, max.level = 1)
List of 2
 $ :List of 3
  ..- attr(*, "class")= chr "shiny.tag"
  ..- attr(*, "html_dependencies")=List of 1
 $ :List of 3
  ..- attr(*, "class")= chr "shiny.tag"
 - attr(*, "class")= chr [1:2] "shiny.tag.list" "list"

注意:整个列表的类从 更改为 just 。有谁知道如何防止这种情况发生?我知道我可以用来手动重新添加类,但这似乎很笨拙。shiny.tag.listlistdo.call(tagList, inputs_new)shiny.tag.list

R 列表 递归 数据操作 HTMLTOOLS

评论

0赞 Bulat 10/5/2019
您需要共享代码以使其成为可重现的示例tagAppendAttributes
1赞 user51462 10/5/2019
这是包中的一个函数,我在代码的标题中包含了一个调用,因此结果应该是可重复的。htmltoolslibrary
0赞 Ronak Shah 10/5/2019
I would like to modify all sublists who have class shiny.tag and whose name element equals label修改到什么?另外,您为什么认为会更改函数中的类?tagAppendAttributesx
0赞 user51462 10/5/2019
不对不起,我想修改那些有类的子列表,并且其第一个元素()相等,方法是将函数应用于它们:. 不更改标记的类。该函数用于更改递归期间不满足条件的标记类。这澄清了吗?shiny.tagnamelabeltagAppendAttributestagAppendAttributes(x, style = 'display:none;')tagAppendAttributeshideLabelx$name == 'label'
0赞 user51462 10/5/2019
基本上,我需要应用于列表中的所有标签标签(标签标签都是具有类 AND 名称 == 'label') 的子列表),同时保留列表的原始结构(该结构显示在我帖子的第一个块的输出中)。tagAppendAttributes(x, style = 'display:none;')inputsshiny.taginputsstr

答:

0赞 ismirsehregal 11/17/2023 #1

从htmltools版本0.5.2开始,获得了该参数,因此我们可以简单地执行以下操作:tagAppendAttributes.cssSelector

library(htmltools)

inputs = tagList(
  selectInput('first', 'FIRST', letters), 
  checkboxInput('second', 'SECOND')
)

inputs_new <- tagAppendAttributes(inputs, style = "display:none;", .cssSelector = "label")

PS:在此上下文中还要检查htmltools::tagQuery()