【问题标题】:Find sequences of elements in vectors查找向量中的元素序列
【发布时间】:2019-05-16 09:49:19
【问题描述】:

我需要一些指示。实际上,我并不一定需要一个成熟的解决方案 - 一些指向函数和/或包的指针会很棒。

问题:我想在字符向量中找到特定的序列。序列可能有点“未指定”。这意味着一些元素应该是固定的,但对于一些元素来说,它们有多长或它们究竟是什么并不重要。

一个例子:假设我想在一个字符向量中找到以下模式:

  1. 序列应以“Out of”或“out of”开头
  2. 序列应以“原因”结尾
  3. 在两者之间,应该有其他元素。但有多少元素(也可以为零)以及元素到底是什么并不重要。
  4. 在 1. 和 2. 之间,不应有“.”、“!”或者 ”?”。
  5. 应该有一个参数来控制 3. 中的序列的多长时间。最大可以仍然产生结果。

函数的返回值应该是向量中的中间元素和/或它们的索引。

所以,函数应该像这样“表现”:

  • c("Out", "of", "specific", "reasons", ".")返回"specific"
  • c("Out", "of", "very", "specific", "reasons", ".")返回c("very", "specific")
  • c("out", "of", "curiosity", ".", "He", "had", "his", "reasons") 返回 "" 或 NA 或 NULL,哪个无关紧要 - 只是一个没有结果的信号。

正如我所说:我不需要完整的解决方案。任何指向已经实现此类功能的包的指针都表示赞赏!

理想情况下,我不想依赖首先粘贴文本然后使用正则表达式进行匹配的解决方案。

非常感谢!

【问题讨论】:

    标签: r string


    【解决方案1】:

    我真的很想知道满足您需求的软件包。我倾向于折叠字符串并使用正则表达式或找一个程序员或使用perl。但这是 R 中的一个可扩展解决方案,还有更多案例可供试验。不是很优雅,但看看这是否有一些实用性。

    # Recreate data as a list with a few more edge cases
      txt1 <- c(
        "Out of specific reasons.",
        "Out of very specific reasons.",
        "Out of curiosity. He had his reasons.",
        "Out of reasons.",
        "Out of one's mind.",
        "For no particular reason.",
        "Reasons are out of the ordinary.",
        "Out of time and money and for many good reasons, it seems.", 
        "Out of a box, a car, and for random reasons.",
        "Floop foo bar.")
      txt2 <- strsplit(txt1, "[[:space:]]+") # remove space
      txt3 <- lapply(txt2, strsplit, "(?=[[:punct:]])", perl = TRUE) #
      txt <- lapply(txt3, unlist) # create list of tokens from each line
    
    # Define characters to exclude: [. ! and ?] but not [,]
      exclude <- "[.!?]"
    
    # Assign acceptable limit to separation
      lim <- 5 # try 7 and 12 to experiment
    
    # Create indices identifying each of the enumerated conditions
      fun1 <- function(x, pat) grep(pat, x, ignore.case = TRUE)
      index1 <- lapply(txt, fun1, "out")
      index2 <- lapply(txt, fun1, "of")
      index3 <- lapply(txt, fun1, "reasons")
      index4 <- lapply(txt, fun1, exclude)
    
    # Create logical vectors from indices satisfying the conditions
      fun2 <- function(set, val) val[1] %in% set
      cond1 <- sapply(index1, fun2, val = 1) & sapply(index2, fun2, val = 2)
      cond2 <- sapply(index3, "[", 1) < lim + 2 + 2 # position of 'of' + 2
      cond3 <- sapply(index3, max, -Inf) < sapply(index4, min, Inf)
    
    # Combine logical vectors to a single logical vector
      valid <- cond1 & cond2 & cond3
      valid <- ifelse(is.na(valid), FALSE, valid)
    
    # Examine selected original lines
      print(txt1[valid])
    
    # Helper function to extract the starting and the ending element
      fun3 <- function(index2, index3, valid) {
        found <- rep(list(NULL), length(index2))
        found[valid] <- Map(seq, index2[valid], index3[valid])
        found <- lapply(found, tail, -1)
        found <- lapply(found, head, -1)
      }
    
    # Extract starting and ending element from valid list members
      idx <- fun3(index2, index3, valid)
    
    # Return the results or "" for no intervening text or NULL for no match
      ans <- Map(function(x, i) {
        if (is.null(i)) NULL # no match found
        else if (length(i) == 0) "" # no intervening elements
        else x[i]}, # all intervening elements <= lim
      txt, idx)
    
    # Show found (non-NULL) values
      ans[!sapply(ans, is.null)]
    

    【讨论】:

      【解决方案2】:

      让我们假设你的例子

      x <- c("Out", "of", "very", "specific", "reasons", ".")
      

      我们首先需要得到指标的开始

      i_Beginning <- as.numeric(grep("Out|out", x))
      

      和结局

      i_end <-  as.numeric(grep("reasons", x))
      

      还需要检查 Out 后面是 of

      Is_Of <- grepl("Of|of", x[i_Beginning +1])
      

      如果这是真的,我们提取其他元素

      if(Is_Of){
      extraction <- x[c(i_Beginning +2, i_end -1)]
      }
      print(extraction)
      

      【讨论】:

      • 谢谢。但是,“真正的”应用程序比我的简单示例要复杂得多。在现实中,我会出现很多“出于”和“原因”,但不一定同时出现。我仍在解决这个问题,但我希望已经有现成的解决方案可以使用。
      猜你喜欢
      • 2014-09-03
      • 1970-01-01
      • 2018-11-26
      • 2016-06-11
      • 2015-04-15
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-09-25
      相关资源
      最近更新 更多