基于正则表达式高亮显示DT中的单词

时间:2019-06-17 14:42:30

标签: r shiny dt

使用DT闪亮,我希望能够突出显示所选单词。设置searchHighlight = TRUE接近我想要的设置,但这也会突出显示包含搜索的单词。例如,如果我要搜索“ on”,它也会与“ stone”匹配,突出显示中间的“ on”。

示例图像:

Link

我可以优化搜索选项,使regex = TRUE不变,但是不会突出显示。例如,如果我想使用“ on | in”之类的正则表达式,也是如此。

示例(包括正则表达式):

library(shiny)
library(DT)
library(data.table)

example_data <- data.table(words = c("on", "scone", "wrong", "stone"), 
                           description = c("The word on", "Scone is not on.", "Not on either", "Not here at all"))

ui = shinyUI(fluidPage(

  sidebarLayout(
    sidebarPanel(
      textInput("word_select", label = "Word to search")
      ),
    mainPanel(
      dataTableOutput("word_searched")
    )
  )
))

server = shinyServer(function(input, output, session) {

  output$word_searched <- renderDataTable({
    datatable(
      example_data, 
      options = list(searchHighlight = TRUE, 
                     search = list(regex = TRUE, 
                                   search = paste0("\\b", tolower(input$word_select), "\\b")))
    )
  })

  })

shinyApp(ui = ui, server = server)

DT已通过反应性表达式过滤在单词上,因此所有字段必定会包含所选单词,但我只是想避免引起用户误以为更长的单词被错误地包含在搜索中的困惑。我没有在示例中执行此操作,但只是确认这不是我关注的元素。

感谢您的帮助。

(已编辑,在示例数据中添加了带有标点符号的单词示例。)

2 个答案:

答案 0 :(得分:1)

您可以创建一个reactive元素,而不是依靠数据表的搜索功能,该元素首先按输入进行过滤,然后将匹配的单词替换为嵌入在<span style="background-color:yellow;">标记中的相同单词。这样可以通过更复杂的正则表达式提供更大的搜索灵活性。

您需要将escape = F添加到datatable,以便正确解释HTML标记。我已将options = list(dom = "lt")添加到datatable中,以删除数据表的搜索字段,并将注意力集中在左侧的搜索字段上。

使过滤条件保持相当模糊的状态,以防止表消失,直到找到完美的匹配为止-也就是说,当您键入“ o”时,表不应消失,因为没有完美的匹配,然后在出现“ on”时重新出现。然后,只有找到匹配的单词(即onOnon.,而不是stonescone等时,高亮才会出现。一窥它的外观:

enter image description here

这是代码。请注意,我使用dplyr的过滤和变异函数是因为它们可以通过其*_all变体轻松地应用于多个列:

library(shiny)
library(DT)
library(data.table)
library(dplyr) # For `filter_all` and `mutate_all`.

example_data <- iris
    # data.table(words = c("on", "scone", "wrong", "stone"), 
    #                        description = c("The word on", "Scone is not on.", "Not on either", "Not here at all"))

ui = shinyUI(fluidPage(

    sidebarLayout(
        sidebarPanel(
            textInput("word_select", label = "Word to search")
        ),
        mainPanel(
            dataTableOutput("word_searched")
        )
    )
))

server = shinyServer(function(input, output, session) {

    # This is your reactive element.
    df_reactive <- reactive({
            example_data %>%
                # Filter if input is anywhere, even in other words.
                filter_all(any_vars(grepl(input$word_select, ., T, T))) %>% 
                # Replace complete words with same in HTML.
                mutate_all(~ gsub(
                              paste(c("\\b(", input$word_select, ")\\b"), collapse = ""),
                              "<span style='background-color:yellow;'>\\1</span>",
                              .,
                              TRUE,
                              TRUE
                              )
                          )
    })

    # Render your reactive element here.
    output$word_searched <- renderDataTable({
        datatable(df_reactive(), escape = F, options = list(dom = "lt"))
    })

})

shinyApp(ui = ui, server = server)

答案 1 :(得分:0)

我不确定这是否是您真正想要的,但是我认为这很接近:这不会执行精确的搜索(例如,“ on”将匹配“ stone”),但是这只会突出显示完全匹配< / em>(例如,“ on”将不会突出显示)。这将使用mark.js库。

dtable <- datatable(iris[c(1,2,51,52,101,102),], 
                    options = list(
                      mark = list(accuracy = "exactly")
                    )
)
dep1 <- htmltools::htmlDependency(
  "datatables.mark", "2.0.1", 
  src = c(href = "https://cdn.datatables.net/plug-ins/1.10.19/features/mark.js"),
  script = "datatables.mark.min.js")
dep2 <- htmltools::htmlDependency(
  "jquery.mark", "8.11.1", 
  src = c(href = "https://cdnjs.cloudflare.com/ajax/libs/mark.js/8.11.1"), 
  script = "jquery.mark.min.js")
dtable$dependencies <- c(dtable$dependencies, list(dep1, dep2))
dtable

enter image description here