【问题标题】:Select a changing specific part in a sentence选择句子中变化的特定部分
【发布时间】:2018-01-07 18:57:50
【问题描述】:

我有一个用例,我必须将一个句子分成几部分。 被切断的部分有一个日期戳(格式如 - 30.12.17/13.24)

文本示例如下所示:

  "BEA   NR:JH8D78   30.12.17/13.24 ALBERT HEIJN 1311 UTRECH,PAS599"

我想删掉的部分是:

 "ALBERT HEIJN 1311 UTRECH"

所以"30.12.17/13.24"之后和之前的部分:",PAS599"

我的想法是这样的:

  1. 在句子中查找包含两个数值、一个点和两个数值的模式(13.24)
  2. 然后在句子中寻找位置并将其切断。
  3. 应用简单的 strsplit 来摆脱 PAS599。

关于这是否是正确的方法的任何反馈?我的假设是有更聪明的方法来削减它....?

【问题讨论】:

  • 您是否打算有很多这样的情况(您有一些类似的日期格式,最后是逗号分隔的值,而您想要的只是中间的东西?)跨度>

标签: r


【解决方案1】:

正则表达式会以一般的方式做到这一点

这是一个例子

# install.packages('stringr')
library(stringr)
sample = "BEA NR:JH8D78 30.12.17/13.24 ALBERT HEIJN 1311 UTRECH,PAS599"
pattern = regex(".*\\s\\d+[.]\\d+[.]\\d+/\\d+[.]\\d+\\s*(.*),.*", perl=T)
result = str_match(sample, pattern)
result[2]

在近似英语中,正则表达式正在执行以下操作

查找任何字符,然后是一些空格,然后是数字模式,然后是一些可选的空格。此时开始一个捕获组并记住逗号之前的任何内容。

str_match 结果的第二个元素是捕获组的内容。

【讨论】:

    【解决方案2】:

    我建议使用 stringr 包来完成您的工作 - 有很多方法可以执行正则表达式,但 stringr's 语法更简单一些。以下是我基于将其转化为函数的建议 - 这是假设您可能有许多结构相同但数据不同的案例。

    library(stringr)
    
    my_string = 'BEA NR:JH8D78 30.12.17/13.24 ALBERT HEIJN 1311 UTRECH,PAS599'r)
    
    get_middle <- function(my_string){
      date <- "(([0-9]{2}[.]){2})[0-9]{2}[/]([0-9]{2}[.])[0-9]{2}[ ]"
      after_date <- str_split(my_string, date)[[1]][2] # Remove date and all before
      final <- strsplit(after_date, ',')[[1]][1] # Remove comma and all after
      return(final)
    }
    

    如果你愿意,你可以让它更简洁,但简而言之,这只是创建一个模式来匹配日期:

    • [0-9] 匹配任意数字的单个数字;
    • 大括号({ 和 })表示连续多少次匹配上一个条目
    • [.] 和 [/] 分别匹配句点和斜线文字

    然后我在逗号上分开。

    【讨论】:

      【解决方案3】:

      我喜欢regular expressions,因为传入的文本没有很好的分隔符。但它确实比strsplit() 需要更多的努力。如果这个任务是你唯一喜欢做的事情,那么学习正则表达式可能不值得。但是一旦你学会了它们,你就会看到很多利用它们的机会。

      以下正则表达式模式提取/捕获“13.24”和“ALBERT HEIJN 1311 UTRECH”。它有点隐藏在模式中,但括号是使一切正常的原因。他们capture您要捕获/提取的输入元素。然后gsub()替换第一个(“\1”)或第二个(“\2”)组的整个匹配。

      pattern <- "^.+?/(\\d{2}\\.\\d{2}) (.+?),\\w{2,}\\d{3,}$"
      ds <- tibble::tibble(
        x = c(
          "BEA NR:JH8D78 30.12.17/13.24 ALBERT HEIJN 1311 UTRECH,PAS599",
          "ABC NR:JH8D78 30.12.17/09.00 Piggly Wiggly 91 Dorestad,PAS601"
        )
      )
      

      regex tester 解释了上述模式中使用的不同标记。如果您需要使模式更灵活,这也是一个起点。 (我对您必须从客户端读取的地理空间输入类型做了一些假设。)当您将模式从测试仪移至 R 时,请记住转义反斜杠(这实际上意味着将单个反斜杠转换为双引号)。

      ds$y1 <- as.numeric(gsub(pattern, "\\1", ds$x))
      ds$y2 <- gsub(pattern, "\\2", ds$x)
      
      
      > ds[, c("y1", "y2")]
      # A tibble: 2 x 2
           y1                        y2
        <dbl>                     <chr>
      1 13.24  ALBERT HEIJN 1311 UTRECH
      2  9.00 Piggly Wiggly 91 Dorestad
      

      【讨论】:

        【解决方案4】:

        我会做两个拆分: 1.- 根据斜线“/”拆分,然后是两个字母数字字符、一个点、两个字母数字字符。 2.- 然后取第一个拆分的第二部分,并使用逗号再次拆分。

        例如:

        t <- "BEA NR:JH8D78 30.12.17/13.24 ALBERT HEIJN 1311 UTRECH,PAS599"
        res <- paste(strsplit(t, "/\\d+.\\d+\\s", perl = T)[[1]][1], strsplit(t, ",", perl = T)[[1]][2], sep = ",")
        res
        [1] "BEA NR:JH8D78 30.12.17,PAS599"
        

        【讨论】:

          【解决方案5】:

          以最简单的形式假设",PAS" 是结尾的固定字符。我使用了vector 来展示转换多行,其中每行将成为vector 的一个元素。

          v <- c("BEA NR:JH8D78 30.12.17/13.24 ALBERT HEIJN 1311 UTRECH,PAS599")
          
          lst <- lapply(strsplit(v, "\\/[0-9]+\\.[0-9]+ |,PAS[0-9]+", perl = TRUE), function(x){
            x[2]
          })
          
          #> lst
          #[[1]]
          #[1] "ALBERT HEIJN 1311 UTRECH"
          

          【讨论】:

            猜你喜欢
            • 2021-09-26
            • 1970-01-01
            • 1970-01-01
            • 2021-01-15
            • 2012-12-10
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多