【问题标题】:Separating A String Into Characters将字符串分离为字符
【发布时间】:2021-10-22 20:32:27
【问题描述】:

我有一些用字符串编码的有序测试结果。字符串可以是任意长度。字符串中的每个数字代表一个测试结果。下面以四个测试结果为例:

2069

我想通过将字符串拆分为单独的观察来在 R 中整理这些内容。 strsplitstring::str_split 没问题,它们会返回四个值,这些值将成为我的观察结果。

strsplit("2069" %>% as.character(), split = "") %>% unlist()
[1] "2" "0" "6" "9"

然而,现在,我意识到有些结果的值大于 9。这些两位数的值已用括号进行编码,以表明它们不是单独的结果。

例如,在下面的例子中,我仍然有四个值,但有些值已经用括号括起来,以便对大于 9 的值进行分组。

2(10)1(12)

我正在努力解决这些问题,以便我得到

[1] "2" "10" "1" "12"

感谢任何指导。谢谢。

【问题讨论】:

    标签: r regex string


    【解决方案1】:

    已更新 - 基于 cmets 中显示的 OP 新模式的模式匹配。在这里,我们使用str_extract 来提取开括号 (regex lookaround) 或 (|) 任何非括号字符 ([^()]) 后面的一个或多个数字

    library(stringr)
    str_extract_all(str1, "(?<=[(])\\d+|[^()]")
    [[1]]
    [1] "2"  "10" "1"  "12"
    
    [[2]]
    [1] "2" "0" "6" "9"
    
    [[3]]
    [1] "2"  "15"
    
    [[4]]
    [1] "2" "1" "3" "1"
    

    -测试 OP 的额外模式

    str_extract_all(str2, "(?<=[(])\\d+|[^()]")
    [[1]]
    [1] "2"  "10" "1"  "12"
    
    [[2]]
    [1] "2" "0" "6" "9"
    
    [[3]]
    [1] "2"  "15"
    
    [[4]]
    [1] "2" "1" "3" "1"
    
    [[5]]
    [1] "10" "0"  "2"  "0"  "1" 
    

    -早期的解决方案(基于假设所有大于9的数字都将被括在括号内)

    我们可以在base R中的括号内拆分

    unlist(strsplit(str1[1], "\\(|\\)"))
    [1] "2"  "10" "1"  "12"
    

    假设如果有这两种情况,那么一个选项是获取那些元素的索引有括号并单独执行此操作

    i1 <- grepl("\\(|\\)", str1)
    lst1 <- vector('list', length(str1))
    lst1[i1] <- strsplit(str1[i1], "\\(|\\)")
    lst1[!i1] <- strsplit(str1[!i1], "")
    unlist(lst1)
    [1] "2"  "10" "1"  "12" "2"  "0"  "6"  "9"  "2"  "15" "2"  "1"  "3"  "1" 
    

    或者另一个选项是ifelsegrepl 来创建单个分隔符,然后使用strsplit

    lst1 <- strsplit(trimws(ifelse(grepl("\\(|\\)", str1), 
        gsub("\\(|\\)", ",", str1), gsub("(?<=.)(?=.)", "\\1,\\2", 
           str1, perl = TRUE)), whitespace = ","), ",")
    lst1
    [[1]]
    [1] "2"  "10" "1"  "12"
    
    [[2]]
    [1] "2" "0" "6" "9"
    
    [[3]]
    [1] "2"  "15"
    
    [[4]]
    [1] "2" "1" "3" "1"
    

    数据

    str1 <- c("2(10)1(12)", "2069", "2(15)", "2131")
    str2 <- c(str1, "(10)0201")
    

    【讨论】:

    • 感谢您的回复,@akrun。我没有足够清楚地表达我的问题,并为清楚起见对其进行了编辑。问题是每个编码值代表一个测试结果,除非该值大于 9,在这种情况下,测试结果用括号括起来。
    • @RDelRossi 我更新了帖子以检查那些具有() 的案例。你能检查一下我的解决方案的第二部分吗
    • 最后一个选项超级紧凑,令人印象深刻,太棒了!
    • 实际上,@akrun,最后一个超紧凑版本,现在也处理了我的异常问题案例。
    • @akrun:太棒了。谢谢你,阿伦,你的帮助。非常感谢。
    【解决方案2】:

    也许我们可以像下面这样(从@akrun借用str1

    > mapply(strsplit, str1, ifelse(grepl("[()]", str1), "\\(|\\)", ""))
    $`2(10)1(12)`
    [1] "2"  "10" "1"  "12"
    
    $`2069`
    [1] "2" "0" "6" "9"
    
    $`2(15)`
    [1] "2"  "15"
    
    $`2131`
    [1] "2" "1" "3" "1"
    

    【讨论】:

      【解决方案3】:

      使用

      (?<=\()\d+(?=\))|\d
      

      regex proof

      解释

      --------------------------------------------------------------------------------
        (?<=                     look behind to see if there is:
      --------------------------------------------------------------------------------
          \(                       '('
      --------------------------------------------------------------------------------
        )                        end of look-behind
      --------------------------------------------------------------------------------
        \d+                      digits (0-9) (1 or more times (matching
                                 the most amount possible))
      --------------------------------------------------------------------------------
        (?=                      look ahead to see if there is:
      --------------------------------------------------------------------------------
          \)                       ')'
      --------------------------------------------------------------------------------
        )                        end of look-ahead
      --------------------------------------------------------------------------------
       |                        OR
      --------------------------------------------------------------------------------
        \d                       digits (0-9)
      

      R code

      library(stringr)
      str1 <- c("2(10)1(12)", "2069", "2(15)", "2131")
      str_extract_all(str1, "(?<=\\()\\d+(?=\\))|\\d")
      

      结果

      [1] "2"  "10" "1"  "12"
      
      [[2]]
      [1] "2" "0" "6" "9"
      
      [[3]]
      [1] "2"  "15"
      
      [[4]]
      [1] "2" "1" "3" "1"
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2017-07-12
        • 1970-01-01
        • 1970-01-01
        • 2015-12-28
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多